D2B reverse engineering info

Many people send me private messages about the D2B protocol. Here is some info how I managed to reverse engineer the data:

The D2B optical transceiver chip is called OCC8001 if you use google you can find basic information on it. The schematics for the Mercedes-Benz Audio 30 is available – just google for “BE3300 service manual” or “BE3300 schematics” you can see how the OCC8001 chip is connected to the optical transmitter; the DAC and the ADC.

The Benz CD-Changers have a separate bard on the back that does the D2B communication. The board contains the OCC8001 chip and optical transmitter and receiver. It also has 3 pin connector for 12V power, ground and “wake up” signal. The “wake up” signal is used to start the device from sleep, when the car is started.

Here is the pinout for the board’s flat cable connector.

Optical IO board
(contacts up) MC3010
17 pin connector

1 – Fsync (pin 12)
2 – SCLK (pin 13)
3 – SR0 (pin 14)
4 – OCERR
5 – GND
6 – OCREQ – Optical input AND gate (pin 1 on TC7S08F)
7 – i2c SCL
8 – i2c SDA
9 – OCINT
10 – WAKEUP
11 – OCRESET
12 – RMCLK (pin 6)
13 – GND
14 – GND
15 – BAT +12V
16 – BAT +12V
17 – VCC +5V

On MC3198 Contacts are down and pin 1 = pin 17

1. Device Addressing

Addresses in the D2B network ring are 12-bit numbers. Each device in the D2B network has two addresses. One is the device position address, which describes the device position in the ring relative to the master – the master has position 0 and position address of 0x400. The first device has position 1 and position address 0x401 and so forth. The devices initialize their position address by a special procedure initiated by the master. This procedure is one of the first things that the master performs.

The second address is the device physical address. Each device assigns it’s own address. For example the master address is usually 0x1c8; The CD-Changer address is 0x190. The device starts with a particular address and probes the network if that address is already taken. If the address is not taken, the device assigns the address to itself, otherwise it tries the next value.

When the master starts the network, it assigns an address to itself. When a slave device is participating in the network it starts with a default physical address of 0xfff. When the slave device first sends a packet to the master, the master would “notice” the device has “unassigned” address and send an “Assign Device Address” command to the slave. The slave would then initiate the procedure to assign a physical address to itself and notify the master.

In addition to the physical and position address, there is a “broadcast” address 0x3c8 – a message sent to that address would be received by all devices in the ring. There is also a group cast address – any other address in the 0x300-0x3ff range. The device must be a member of that group to receive the message. Each device decides what group it is a member of – there is no set procedure for that. Each device is a member of only one group at a time (limitation of OCC8001). I have not observed any group cast messages being sent.

2. Message Format

Each message is up to 16 bytes long. Each message has a type and a length encoded in the message header. The receive and transmit buffer formats are:

<address><type|len><message data>

Where the address is the source or destination address (depending whether you are receiving or sending a message). The address is 2 bytes with the LSB byte first and the top 4 bits 0 on the second byte. The third byte contains the message type – 4 high order bits; and the message length – 1 in the low 4 bits. A message length of 0 means 1 byte long message. A message length of 0x0f means 16 bytes long message. A message is minimum 1 byte long.

The receive and send buffers are 19 bytes long total. I have not been able to decipher much of the data messages being exchanged, just enough so I can simulate a CD-changer being connected to the network.

3. Errors

A message transmission could fail. Usually because the target device’s receiving buffer is not free. Thus when sending a message one has to check for “successful transmission” flag. Luckily the chip handles the acknowledgement and errors automatically. All you have to do is check if the transmission succeeded or not. It is suggested that an app retries up to 5 times to send a message if the transmission was unsuccessful.

Errors due to loss of signal are very rare and usually indicate a problem with the cables. In this case a device detecting the error just shuts off breaking the ring. Eventually the master would shut off the whole ring. Momentary loss of carrier is tolerated if the loss is less than 20ms.

4. Chip communication

The D2B optical controller is called “Conan” the chip is labeled OCC8001 and sometimes OS8101. These are the same identical ship. There is a brief data sheet available for OCC9001 – but that chip was meant to be way more advanced. Anyway the chip can use i2c or SPI for communication in the Audio 30 it is connected via i2c.

The chip’s i2c address is 0x46. I used a logic analyzer to sniff the communication between the CPU and the chip. The chip uses a protocol similar to other i2c devices, when writing the first byte is a “register address” the second byte is the value that is written to that address. If more than one value is sent the next value goes to the next address etc. When reading the CPU first sends a “write” request with only an address – which is the address where it want’s to read; The the subsequent device read requests read first value from that address, next value from the next address etc. until the CPU terminates the transfer.

The chip receive and transmit buffers (19 bytes each) are located at i2c addresses 0x6b and 0xaa respectively.

Happy hacking.

Jaguar D2B CD-changer details

Many people ask how to build one. Let me tell you it is not very easy.

The device consists of two parts a D2B audio controller and a Raspberry PI which handles the Bluetooth streaming. The latest version of the unit user Raspberry PI Zero – the regular, not WiFi version.

The two boards connect together via 40 pin header. The D2B unit receives audio via I2S protocol from the Rapsberry PI. The two units also communicate via serial interface. The Raspberry PI is powered by the D2B audio unit. The D2B audio unit also can reset the Raspberry PI board if it is not responding to serial commands.

Here is the schematics of the D2B unit. Jaguar D2B board

The micro-controller is Cypress PSOC4 4100 series. Here is the firmware it is running.

The Gerber files that one can use to make the PCB.

The fiber optic connector is 3D printed. Here are the model files. There are 3models for the 3 parts of the connector. The optical receiver is EAPLRBA0 the transmitter is EAPLTBA0

Instructions how to built the software for the Raspberry PI board.

You would need a micro-sd card for the Raspberry PI and a Bluetooth USB dongle (The ones marked with CSR 4.0 work fine)

Soldering machine improvements

I was very confident in my soldering machine from the tests I conducted the previous week. I decided to program a whole board and try it out.

Alas the confidence was premature and multiple failures ensued. Here is an example

I tried many things, but the soldering wire was hitting the pin and was not melting. I tried re-aligning the needle to point to the solder iron tip instead of the pin. This did not produce improvements at all. I had to aim fairly high to avoid hitting the pin and now the solder was not flowing down and bulging.

I was getting frustrated and decided to look at a few videos of commercial soldering machines for inspiration.

After a few hours I devised a new mount for the soldering needle. The previous mount was allowing adjustments only in the angle of the soldering iron as well as the needle. This configuration seems quite limited. Applying maximum effort here is the new plan:

Now the syringe is mounted on this dual clamp. The clamp allows for both items to rotate. The other end of the clamp is connected to a 3mm steel rod, which adds another degree of rotation. Finally the rod is connected to the mount plate with a plank which allows both: XY movement as well as rotation.

Here is the final assembly after a few dozen failed 3D printing jobs

The new mounting system adds quite a bit of flexibility to the position of the needle that guides the solder wire. Hopefully I’ll be able to find a location which works in most cases.

 

Soldering machine tests

I’ve been running the soldering machine for about 2 weeks. I added a very ugly, but effective fume extractor to the machine head.

It has 40mm fan and a square piece of carbon-activated filter to absorb the fumes. The design is not my best work and is held together with hot glue. However it does work.

Some early failures of the soldering were quite comical:

But some tweaks of the G-Code and it is mostly working now

At this stage it is completely manual programming. No computer vision at all. I’m recording all soldering sessions so they can be used for training ML models later.

My test board is fairly straight forward, so programming the G-Code is not hard. I use a simple C++ program to send the commands to the 3D printer controller. This allows me to add the necessary delay and in the future integrate some processing of the camera image.

I also managed to find an M12 camera lens with much less distortion, to the point that the image no longer needs corrections.

Computer vision mishaps

I was planning to add a Raspberry Pi camera on my soldering machine. I used a camera board from China which has the M12 lens mount. There is a variety of M12 lenses and one can play with the focus.

This is the camera board mounted on the soldering head

I finally got everything set up. I discovered this very nice camera streaming web interface package here is a picture of the web interface

The UI is simplistic, but allows control of the camera settings and while streaming is consumes only 3-5% CPU. Well done to the Raspberry Pi foundation and the RPi Cam Web Interface team.

Here is an image I captured with the camera

The focus looks good and the image resolution is very nice. However the vertical blue edge of the plastic mount is supposed to be straight. Not so much on the image. The 3.6mm M12 lens I used on the camera adds quite a bit of distortion around the edged. My other lenses are more on the telephoto side: 6mm, 8mm, 12mm and 16mm. I tired the 6mm lens and the distortion was better, but the field of view was too narrow and wan not capturing the soldering head. I ordered some more lenses which claim “low distortion”. We’ll see it they produce better result.

My initial goal was to capture a series of images and then “stitch” them together with OpenCV. Initial experiments failed miserably. First the lens distortion was confusing the stitching algorithm. I know that OpenCV has camera calibration option which can correct lens distortion, but I’ll try better lens first.

The other issue with the stitching was inconsistent lighting. I tried using my LED photo light, which helped initially. Still the lighting on some spots was low and some spots were too bright and getting lots of reflection from the PCB board surface.

I constructed this new camera head, which allowed me to mount a small ring of LEDs close to the camera.

I seemed like a good idea at the time, however it makes terrible reflections onto the PCB. So back to square one. I’ll make some combination of external photo light as well as some white LED strips. The goals is to have uniform light with minimal reflection and not to obstruct the movement of the machine.

Soldering automation (attempt 1)

I was researching how to make my 3D printer controller as scale. The usual option is to make a large purchase order from a manufacturer in Asia, but why not try a different way.

The issue with ordering from a PCB assembly house is that to make the process economical you have to place an order for 100-500 boards. For smaller batches it takes too much effort for the company to setup the machines. As you can guess ordering 500 boards is not exactly an affordable affair and mistakes are very costly.

I can make PCB production fairly efficiently. The most time consuming step is soldering all through-hole connectors on the board.

So why not try to automate that? As one of my favorite superheroes often says: “Maximum effort”.

I was inspired by this video:

I liked the idea of using a dispensing needle to guide the solder wire. However I wanted a bit more control over the angle of the solder iron and the solder wire.

This is a video of my first attempt to test the soldering tip mount. I used Hakko T12 tip with a soldering iron controlled from KSGER (aliexpress).

I’m planning to mount this contraption on a Prusa MK3 chassis. The plate on the bottom is designed to mount on the X axis carrier of the Prusa.

TMC2130 catches fire

A co-worker shared this story yesterday with me. He upgraded his printer to TMC2130 drivers and while he was testing how the new toys performed he got a message that one of the drivers overheated and then the driver exploded in a non trivial ball of fire.

I asked if I can have the driver for some pictures. The driver boards were clones from the usual Asian markets. He now has ordered some “legit” boards from DigiKey. Crossing fingers these would not burn his house down. Said unfortunate driver was on his Z axis and he was running it at 1.1 amps.

This is what it looks like, next to a working board from the same supplier:

(click on the image for better resolution)

As you can see the top of the board kind of exploded, with some of the copper traces melted away. I suspect when the driver overheated either a solder joint shorted or the board shorted internally and that caused the severe failure.

This is the bottom of the board, where the driver chip is mounted:

The damage looks less severe from the bottom. There are charred components, but no melted copper.

Here is the top part – where the copper melted under my microscope:

Another angle – close to the edge of the board:

This is the bottom side – you can see the chip is a bit burned and some capacitors have been barbecued.

Another view of the barbecue area:

The rest of the chip looks intact:

I removed the chip an this is a view of the PCB underneath:

All but 3 pads look in very good condition. Unfortunately the 3 pads have evaporated completely from the board as well as the chip itself:

I was wondering if the chip can be salvaged, but it does not appear to be within my abilities.

One more reason to keep a fire extinguisher handy and not let your 3D printer unattended.

TMC2130 does not cooperate :-(

Trinamic drivers are a marvel of engineering. However they combined many things in a single chip that it is hard to make it all work right. Well, it is hard for me at least, if you have mastered these drivers please let me know.

It started when I tried to test if the Marlin firmware for my board would agree to move the stepper motors around. To test the motor driver signals on the board I modified one of the tmc2130 arduino library samples like this, and it was spinning the motor. Alas my enthusiasm was short lived, when I tried to move the motor with Marlin, it would stutter and vibrate, but no motion.

Hmm, I checked and re-checked all the tmc2130 driver settings back and forth. Read the datasheet 3 times – nothing. I was going back and forth between the marlin firmware and my little test program to figure out what was wrong. Finally I was able to isolate the issue to the number of microsteps the driver was configured to take.

Now to be fair the microstepping configuration was not the issue per se, it was a setting I can change to introduce the same problem in my test program as well.

Let’s take a step back and explain what this all means. Stepper motors come in many different configurations. We’ll focus on bipolar 2 phase motors – these are the most common stepper type used for 3D printers. By far the majority of these motors are manufactured to make 200 steps per full rotation. Each step being 1.8°. There also high resolution motors which make 400 steps per rotation or 0.9° for each step. For the purpose of this description the difference is irrelevant.

In the 1.8° motors, it is common to say the 200 steps are “full steps”. In other words the rotor rotates from one stable position to another. In electrical terms, each motor coil is energized fully in one direction or the other.

Clever folk however discovered that they could achieve better precision if they don’t fully energize the motor coils – hence micro-stepping. The most obvious downside of the microstepping is reduced motor holding torque. There are different microstepping options offered by different stepper motor driver chips. Most common are 2, 4, 8 or 16 microsteps. This means that the driver would use 400, 800, 1600, 3200 microsteps to make a full rotation of the motor shaft. Some drivers offer 32 microsteps as option. The tmc2130 and other drivers from Trinamic also offer 64, 128 as well as whooping 256 microsteps. That is astounding 51, 200 microsteps per rotation or about 0.007° per microstep.

Before you get too excited, keep in mind each increase of the microstepping level comes at the expense of decrease in torque.

All these wanders aside, what was my issue with microstepping? I made a simple observation: my test program was driving the motor stepping pin at about 48kHz; with the default settings (256 microsteps) the motor would move, but when I switch to 16 microsteps the motor would make a high pitch sound, but not move. Why? I was puzzled.

Another week of experiments and I discovered the most benign of reasons – I was driving the step pin too fast. In the 256 microsteps configuration the motor speed would be a little under 56 rpm. In the 16 microsteps configuration it would be about 900 rpm. This was above the physical capabilities of the motor with that setup. I found this calculator and it seems with 0.6A current at 12V this motor could theoretically do about 850 rpm max. Practical measurements showed that even at 32 microsteps the motor has trouble moving. At 64 microsteps it was working.

But why does this matter? Well I found that marlin’s default speed is a 300mm/s. I did not change the default axis per mm configuration it was set to 78.74 for 16 microsteps. This would translate to 23,622 microsteps/s or 443 rpm for the motor. Practical test showed this motor was able to achieve about 230rpm max.

Now what? Very simple – I lowered the motor default speed in marlin and was able to issue commands to move the axis 😉

While I was investigating the issue. I got myself a current probe for my oscilloscope. I was able to shoot a few pretty pictures of the driver current of the motor coil trough some different driver settings.

The current probe I got was Hantek C-65:

Picture of the motor driven with full steps an no load. This graph represents the current that goes trough one of the motor coils. There are two coils that drive the motor, the current trough the other coil is identical, but shifted one quarter pulse (90°). The current swings from positive to negative each 2 full steps.

Current waveform with the driver configured for 2 microsteps and 600mA RMS current:

Waveform for 4 microsteps configuration:

Waveform with 16 microsteps:

The waveform with 256 microsteps looks like a smooth sine wave. Sorry I dodn’t manage to get a picture.

This driver has an interesting feature – microstep interpolation. When you enable it, the driver uses 256 microsteps internally and whatever you had configured externally. For example here is the waveform with 2 microsteps and interpolation enabled:

The following is the waveform for full step (no microstepping) and interpolation enabled:

The last image I thought was cool was a capture of the driver waveform changing when the motor is stalled. The configuration is 256 microsteps, with 300mA current. I was trying to stop the motor by holding the shaft with my hand.

Gerber Viewer updated UI

Some time ago I wrote an online Gerber file viewer. I’ve been using it to validate the KiCad Gerber output files, before I sent them to the PCB manufacturer. One feature that was missing was the ability to set transparency on the layers, when more than one layer is selected for display.

As I started working on that, I realized that I also need to be able to select the color for the layer as well. Here are a few screenshots of the viewer in action.

Two layer PCB, top layer is red, the bottom is green:

Six layer PCB (Beagle Bone XM) with top and two internal signal layers selected:

The same Beagle Bone XM board with 6 layers selected: