I managed to assemble a few driver boards. Here is the V2 board loaded with 3 TMC2660 drivers and 3 TMC2209 drivers:
I also got marlin to load and communicate with the drivers. More testing tomorrow.
Here is my first assembled prototype of the V2 board. I only had patience to solder 3 PCIe connectors and skipped on the Thermocouple and servo connectors for now.
Sorry about the “no clean” solder paste gunk around the fuses. I noticed it after I took the picture.
Here is a picture with the driver boards in the slots
And slightly different angle
Here I added a 40x10mm fan for scale comparison
I’m not set on the 40mm fans for cooling, I ordered some 60mm and some 50mm and will do some experimentation what would be the best combination.
Next, I’ll make some driver boards and start porting Marlin to test the contraption.
Many thanks to the awesome team at JLCPCB. I’m really impressed by the speed and the exceptionally low prices. I ordered a set of prototype boards for the V2 design on Oct 28th and they arrived today at my door. Total 8 days including shipping from China.
Here it is 150x105mm 2 layer board:
I ordered the 2660 drivers also from JLC, but I don’t like the red mask color:
The 2660 driver is 4 layer board with “gold fingers” – this is code for the board edge PCIe connector.
The purple board is the 2209 driver. That board is from ohspark. No much difference between the two, except the ENIG finish is standard on oshpark and the purple color is dope. The JLC board comes with a little chamfer around the connector, which is nice.
This is what the driver board looks like plugged in a PCIe slot.
Reflecting on the PrntrBoard V1, there are many good things that I managed to accomplish:
When I started 2 years ago, there were very few 32-bit boards with comparable features. Now there is quite a bit of them. I was trying to find what makes one design more popular than the other and in addition to the board features it comes down to flexibility.
In PrntrBoard V1 I was trying to provide superior cooling solution compared to the tiny replaceable driver board used everywhere. However that choice came at the expense of a monolithic design, which was expensive to make and costly to evolve. Every time I wanted to use a different driver chip I had to re-design the whole board from scratch. It was not going to be sustainable in the long run.
Announcing the PrntrBoardV2: combining all lessons learned and expanding the versatility of the design.
First major change is that the motor drivers are no longer part of the board. Because I still find the original Pololu driver form factor very limiting, I designed the motor driver carried boards to use PCIe slots instead of pin headers.
Here is what the carrier board looks like
The board has 32-bit Arm micro controller – my favorite STM32F407. There are 6 stepper motor slots, with support for 6 thermistors or 6 thermocouples (vie external boards).
There are 4 power MOSFET outputs (1 bed and 3 heaters) and 5 low power MOSFET outputs for fans or LEDs.
Connectivity is via traditional USB, micro-sd card. There are 2 more serial ports for a smart LCD controller and WiFi extension.
I have the traditional RAMPS LCD expansion headers, which should support a variety of LCD screen designs.
Last but not least there are 8 end stops and the ability to route the stall detection signal from the steppers to individual end stops or a global “Alarm” signal.
Drivers are on separate boards with PCIe card edge connectors. This is what the TMC2660 version looks like
And this is what the TMC2209 version looks like
I added some mounting holes next to the PCIe slots so the drivers would not wiggle out of the slot with extensive vibrations.
These driver boards are much larger than the Pololu drivers, which would allow for superior cooling and the ability to have more board real estate for complex designs and or big driver ICs.
In addition the driver boards are mounted vertically on the carrier board, which saves space on the carrier board and allow for excellent air flow trough the drivers with a pair of 40mm fans.
Last but not least because of the reduced requirements on the carrier board, I can use 2 layer instead of 4 layer board, which makes the cost even lower.
I can’t wait to make a few of these and run them trough some tests.
I did some simple thermal tests on the TMC2209 board. In theory these driver chips can supply up to 2A RMS current to the motors. Silent StepSticks with the same drivers are rated around 1.2 to 1.4A depending on the manufacturer.
I used all passive cooling. Ambient temperature was 25C. I used a small 9x9x12mm heatsink on top of the driver chip. These are commonly used on the TMC2209 StepStick boards from China (FYSETC or BIGTREETECH). These are not great, but that is what I could fit in the space. I’ll try to move some of the capacitors to make space for a larger heatsink.
On the bottom I used a 20x14x6 heatsink. Not ideal, but that is what I had laying around. There is enough space for a much larger one (25x25x8 for example).
I used a Seek thermal camera “mounted” on a small microscope stand and connected to my old Nexus 5X phone.
First I tested it at 1A RMS current. I use several very slow speed motion commands (G1 Y250 F50 followed by G1 Y0). I found that slow speed motion is much more challenging to the driver heat wise.
After about 20 minutes it board heated to about 47C on the top:
The heatsink was barely warm to the touch. In my experiments the top of the drivers always heats up more than the bottom, probably because of the relatively large thermal mass of the PCB itself.
Next I ran the board at 1.4A RMS. This was more challenging test for the heat dissipation. It took a while for the temperature to stop rising. It stabilized at around 64C on the top:
And around 55C on the bottom:
In the picture the heatsink looks “cool” because the camera can not compensate for the different emissivity of the bare aluminum.
Both top and bottom heatsinks were considerably hot to the touch. Not “burn your fingers” hot, but “I cant keep my fingers longer that 5 seconds” type of hot.
In both cases I did not get any over-temperature warnings from Marlin. I would say 1.4A is the limit on convection heat dissipation of this board in this configuration.
The Seek camera has around +/ – 5C accuracy.
I did one last test at 1.8A RMS. This was on the extreme side of the capabilities of the board. The temperature of the driver kept climbing slowly. Once it reached around 75C on the top I got an overheat alarm in Marlin, so I turned the power off.
I’m confident with some active cooling the driver would be able to run at this setting, because it took quite some time to get to the alarm.
I just got Marlin to boot and move the motors. Had to make some tweaks to the serial port configuration, because I have unique setup (X, Y and Z share one serial port) and the two extruders share another. I also use proper hardware serial ports, not the SoftwareSerial library. At the moment the code requires special patches to the STM32Duino core and the Trinamic library so it can properly support serial half-duplex communication.
On separate topic, I got a prototype of an LCD i/o board for the Nucleo-F407. I tested it with the REPRAP_DISCOUNT_SMART_CONTROLLER and was working flawlessly.
Here it is connected to my soldering machine:
The very first prototype had a bug, hence the little red wire. This adds support for the traditional EXT1 and EXT2 connectors that are popular with other boards. Graphics panels would require a little work, to convince marlin to use the second SPI hardware block.
Good news first: I managed to get one motor moving with a simple Arduino sketch.
I’m starting to hate QFN packages with a passion. I spent a whole afternoon trying to re-work two pesky drivers. The chips would not communicate via the UART port, no matter what I tried. Finally traced the issue to a bad solder joint on the QFN package and boy these are hard to spot. Simply re-heating the drivers and re-positioning was not enough, I had to remove the chip, add more solder paste, melt it, then re-insert the chip, wipe the excess solder with a soldering iron and finally re-flow the chip one more time. Complete and total PITA.
To top it off this destroys any near by plastic connectors, so now I have the drivers in-place but have to re-solder the connectors back. This would be an endeavor for the next week.
Now all 5 steppers are communicating with the MCU reliably. I had to add support for half-duplex mode to the stm32duino core. The proposed changes are still pending, but I verified that the TMCStepper library is able to communicate with the drivers.
This took me whole day. Working with QFN drivers is plain PITA. It does look good though. I just hope it works.
I finally figured out how to wash most of the flux from the board. It is still not perfect, but looks really good.
I have another revision with 3 fuses. I figured that one fuse for both motors and extruder heaters may be too taxing. In my latest design I have one 15A fuse for the heated bed; one 10A fuse for the extruder heaters and one more 10A fuse for the rest of the electronics.
I maintain a separate fork of Marlin with some tweak that enabled features specifically for the PRNTRBoard. The code is located in github.com .
Last weekend I spent some time adding some minor, but useful updates. First I finally got to enable support for the sd-card reader on the Nucleo-F407 board. It took a while because typically Marlin uses SPI to communicate with the sd-card. However the STM32 has much better hardware module (SDIO) which allows excellent transfer speed.
So it took some time to research what is the simplest way to add SDIO support to the Marlin firmware. There was already support for the STM32F1 series CPU, but it was written using a deprecated library (libmaple). Long story short it is working fine now. The code is in the f407 branch.
The second feature I wanted to enable is the ability to store the printer settings. Usually this is accomplished using I2C or SPI EEPROM chip. Alas I did not add one to the Nucleo-F407 board. I added an SPI flash instead.
The difference is small but significant. EEPROM chips are small, but can sustain millions of data re-writes. In contrast SPI flash chips are relatively large (the one I use is 2MB), but can only support around 100k re-write cycles.
There were two possible approaches, one use the sd-card as storage. This was already supported in the Marlin firmware, so I simply ported to code. The disadvantage is that it depends on the presence of an sd-card in the slot.
The second approach is called wear leveling – using the fact that I have relatively large storage and spread the writing operations across many locations in the chip. This way if I spread the write operation evenly across 100 separate locations I’ll achieve 10 million re-write cycles.
The error leveling code is relatively simple. For the curious you can find the changes here.
Next I finally decider to make a converter board for RAMPS style LCD controller modules. The files are checked in the main PRNTRBoard github repository. I placed and order for a few prototypes – they should be arriving in a week or so.
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:
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.
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.