Ian M's £99 ZHUHAI CTC DiY I3 3D printer

From richmondmakerlabs.uk
Jump to navigation Jump to search

Back to Ian M's profile

The ZHUHAI CTC DiY I3 Pro B 'Prusa' clone printer is rather similar to RML's Geetech I3 Pro B except with a laser cut plywood frame instead of acrylic, and cheapened in many key areas, which I'm working on upgrading. Its my personal 3D printer and is not kept at RML.

The DiY kit and the build

Here's CTC's official build video: https://youtu.be/PSzcU48wczk

Differences on my printer

  • IEC power inlet (Video has direct attached mains lead)
  • Bed levelling screws have countersunk heads so there are no obstructions at the bed corners

Hints & Tips that didn't make it into the build log

  • Buy a pack of M3 washers and insert one in each T-slot in the frame, between the nut and the wood it bears on, to spread the pressure and prevent the nut chewing the wood.
  • A pair of M8 nuts can be used to 'hang' the lead screws and gantry assembly from the top of the frame while working on the steppers or shaft couplers.
  • Put a *VERY* large cable tie right round the body of the extruder and X steppers, with the tail coming straight up at the back of the extruder, and straight down off the X stepper, then cable tie the wiring to the big tail to anchor it before you spiral wrap, Leave the big tail full length inside the spiral wrap to stiffen the loom near the motor. A similar large cable tie round the lower right board fan standoff, snug but not tight so it can pivot on the standoff, can be used to anchor the lower end of the X loom.
  • The 2004 control/display PCB is probably being warped by its plywood frame and the absence of spacers between the board and the back not allowing for the solder joints with slightly protruding header pins. Dismantle it and shim for clearance behind the board with nuts/washers/etc. taking care not to short anything. You may need to file out the bolt holes in the ply so the board fits properly without being forced into a curve before reassembling and mounting it.

Build log from my posts on the RML Telegram group

Currently, a mostly verbatim copy of my 3D printer related posts, with some corrections and additions to my posts + some responses to my posts from other members. If you feel I've misrepresented what you said, or you don't want to be quoted, and you don't have edit rights here, PM me on Telegram!

ToDo: Transfer more stuff from Telegram here and edit it into a coherent project writeup.

6 Jan 2022 - Arrival and initial mechanical assembly

A cheap (£99) Prusa i3 clone 3D printer kit should be landing on my doorstep later on this afternoon . . .

{photo from manual, not posted here due to copyright}

It arrived.
Its actually a ZUHAI CTC DiY I3 PRINTER with a wooden frame, and an ANET A8 v1.5 clone controller board. That’s more or less what I expected as a *real* Prusa for under a ton just isn't happening unless its a BER parts mule. Next: dig through the documentation, such as it is . . .

Mike: “Hi Ian, is it £99?”

Yep. It was £99 from Amazon. https://www.amazon.co.uk/gp/product/B015GDDXJA
I've done the full mechanical assembly, and knocked off for the night *WITHOUT* starting any wiring.

For anyone else contemplating this one, beware: the rails are steel tube, not rod, it has plastic slider bushings not linear bearings, and the Z drive nuts are aluminum, not bronze or brass. Also the filament drive is not adjustable for pressure, and there are very few free GPIOs on the controller available for custom stuff. (There's the three SPI pins of the ISP port J3 if you disable SD card support, one pin on the LCD connector reserved for a beeper on some display boards, and I suppose you could free up two more analog capable pins and UART1 TX & RX if you added an I2C LCD driver board.)


As soon as I've got it dialled in I need to print a cover for the back of the IEC connector, and do something better than the flip-up cover over the PSU mains terminals. I ended up putting a rubber boot made from bicycle inner tube over the back of the IEC connector secured with cable ties as it was just too unsafe adjusting the right rear bed levelling screw without insulation there.

I've already improved the rigidity considerably by adding four M8 nuts and washers to clamp the vertical frame to the M8 allthread that joins the front and back end plates. If you do the same, you *MUST* align the frame and endplates on a dead flat surface*, and as you tighten the new nuts, use a straightedge to check you aren't bowing the vertical frame's lower cross-member. Check you get the front on again dead square. While you are in there, put a nut in the hex hole in the Y axis belt tensioner so the bolt stays put while you adjust the wing nut.

I'm sure I'll be buying other bits for it, once its up and running. e.g. flexible couplings + bearing balls for thrust for the Z screws to reduce shimmy, cheap but real linear bearings, and an all metal adjustable pressure filament drive upgrade kit.

* The flatness of the assembly surface is crucial - 0.2 mm lift of one side of the front plate relative to the rest of the frame, becomes 0.1 mm of varying bed tilt as the bed moves from min. Y to max. Y or visa-versa, giving the illusion the bed surface is saddle shaped, but also resulting in increasing lateral distortion the greater the print height is above the bed rails. Once assembled flat and true, it *should* be operated on an equally flat surface to maintain alignment, but if your table is of questionable flatness, the printer can be shimmed under its frame, and front and back plates to maintain six points of contact, and its position on the table marked to remind you to keep it in the position you've shimmed flat for it.'

9 Jan 2022 - Wiring and problems

Doing the CTC I3 3D printer wiring neatly took most of Saturday afternoon. Then it didn't work! 😢
Back in January, the extra board above the main board (to combine the normal Z limit switch and the BLtouch probe output), and all wiring to it was not present, and only the standard single short-lever Z limit microswitch was fitted.

The main board and wiring

Diagnosing its ills took the whole evening - one of the Z steppers had a broken wire. After carefully teasing the offending pin out of the stepper cable connector, I cleaned out the old crimp and soldered it and both steppers stepped uncoupled. It helps to use a couple of M8 nuts, put on the tops of the Z screws to hold them up so the X axis doesn't have to be dismantled when working on the Z steppers and couplings. The left side was binding and the right side wasn't a whole lot better. Turns out the laser cut bracket motor mounts don't line up with the screw when the Z axis is near the bottom. It’s fiddly but it is possible to remove the motors without extra dismantling. Some careful filing to elongate the mounting holes to line up the motor and final tightening after the coupling was slid over the screw end, and it no longer binds.

However, it still failed to home. 😾 Investigating the limit switch signals found the odd one out was the Y axis which read as homed when it wasn't. The switches are all NC microswitches, and I was getting ready to replace it, when I found its connections failed the tug test on both wires! The wires were broken under enough OEM heatshrink to confuse the issue. Resoldering them and applying new heatshrink fixed that and it now homes.

I suspect the motor wire was a bad crimp, and the switch wires most likely broke because they were 'flapping in the breeze' while the bed, Y axis and lower frame assembly was being packed and shipped.

Finally I was able to test the full range of motion of all axes, do a quick & dirty manual bed levelling and set the Y zero limit screw as low as seems reasonable. (I had it high to avoid crashing the nozzle earlier.) Selecting PLA warmup showed both the heated bed and the hot-end were working, and stabilized at their setpoints, though I'm getting an initial 10 deg C overshoot during hot end warmup, so it probably needs some tuning.

I then tried to load and feed filament - no joy - it didn't want to feed, and when I manually encouraged it all I got for my trouble was a clogged hot-end. Taking the extruder off, dismantling it and careful reassembly of the feeder got it feeding, but I still had the clog to deal with.

I suspected the PTFE tube liner in the heat-break wasn't seating properly, which is what probably caused both the feed problem and the clog. I dismantled the hot-end and extracted the PTFE tube - clogged solid and fatter than the throat at the top of the heat-break tube. I managed to press the clog out with the stem of an Allen key, then close inspection of the PTFE tube found neither end was square. I shaved the better end square, and chamfered the entry to the other end by twiddling a sharp drill bit to stop the filament catching on its edge. Clearing the nozzle was a PITA, eventually it succumbed to a cold pull done off the hot end, supporting the nozzle with a small ring spanner and heating it with a lighter.

I then bench tested the extruder, and it now feeds and extrudes, (manually using the axis menu). Its really fiddly to bolt back on to the X carriage without stripping it to separate the bracket, but after a lot of faffing about and some rather unparliamentary language I got it back on properly, leaving it loaded with filament from the bench test.

Finally I checked it still homes and that the bed levelling hadn't gone too far out while I was working on it, and shut it down for the night.

ToDo: Try printing something!

9 Jan 2022 - Q&A with Ian B, dangerous mains plug, and sellers 'bait & switch'!

Ian B: “Ian, that's quite a log of problems solved. It certainly shows a lack of QC from the manufacturer.

It seems you've approached each fault methodically. (I would expect nothing less from you.) Heating the extruder with a lighter is something I've never heard of before, useful technique.

I wish you luck with the first print. Keep it small and simple.

Then I wish you ongoing luck with all subsequent prints, too.”

If you try my lighter trick, to avoid bouncing a hot-ish nozzle round the room, it would probably be a better idea to screw the nozzle into a M6 nut, and hold it in mole grips with card for thermal isolation from the grips, and clamp the grip handles flat in a vice. The nut will also increase the thermal mass making the whole process more controllable.

I forgot to mention the illegal ('The Plugs and Sockets etc. (Safety) Regulations 1994' - UK Statutory Instruments 1994 No. 1768) undersized and unfused mains plug on its supplied IEC lead. Its pins were so far undersize that there was no retention force in a standard socket!

John Ward on these counterfeit leads & plugs: https://www.youtube.com/watch?v=9KMrWupFQt4
AITA if I try to nail Amazon's balls to the wall for "not as described" and the illegal mains lead? It was still a reasonably good deal as supplied . . .

Description from Amazon product page at time of sale

  • Brand Josef Prusa
  • Material Carbon Fibre

Product description - Technical specifications

  • Print area - 8x8x8 inches (20x20x20 cm)
  • Open frame design for easy use
  • Integrated LCD for use without a computer
  • SD card support (8GB included) and USB port
  • Geniune E3D 1.75mm hotend and RAMBo mini motherboard
  • Easy multicolor printing feature based on layer height
  • Layer height from 50 microns
  • Heated print bed for warpless printing from any material
  • Supported materials - PLA, ABS, PET, HIPS, Flex PP, Ninjaflex, Laywood, Laybrick, Nylon, Bamboofill, Bronzefill, ASA, T-Glase, Carbon-fiber enhanced filaments...
  • Step size in X/Y axes - 10 micron
  • 2 lbs (1 kg) Silver PLA included


  • Not a genuine Josef Prusa printer - its a ZHUHAI CTC ELECTRONIC CO. model.
  • Plywood frame, and no carbon fibre components
  • Less than 20cm X travel - measured 18.6cm from mechanical limit to limit
  • No SD card supplied
  • Not a "Geniune (sic) E3D 1.75mm hotend" - its got a bargain basement generic clone hotend
  • Not a "RAMBo mini motherboard" - its got an Anet A8 v1.5 clone, with a lesser MCU, no max. endstop switch inputs, one less thermistor input, and only three PWMed MOSFETs, so only one controlled fan can be connected.
  • No "2 lbs (1 kg) Silver PLA included" - Three sample coils of approx 12m each, total under 120g supplied

12 Jan 2022 - First Print and another defect found

The CTC I3 3D printer prints!

I'm currently using Cura 3.2.1, and so far have done a test cube and am currently trying an Arduino Mega2560 'bumper' generated from an OpenSCAD library. I aborted the first run after a couple of layers to have something to check against the Arduino board - it looks reasonable, so I'm doing a proper run, and hoping it comes out well enough to use.

More defects found! The X tensioner bolt has a really crappy rolled thread and wont hold in the wing-nut. An ordinary M3 nut on it has just enough grip to be usable. I need to replace it with a long M3 machine screw, so I can get a nut into the tensioner body to hold it, so it doesn't spin when I adjust the wing nut. Subsequently fixed with a length of M3 stainless allthread, with the end mushroomed slightly and a hex nut Loctited on flush to effectively make that long machine screw.

Next job will be to see if I can backup the existing firmware then look at what it takes to get Marlin built for an Anet A8 v1.5 controller, and configured for the CTC I3 3D. Once I've got a usable 'stock' firmware, I can look at the upgrades I want to do, as even swapping out the extruder's filament drive mechanism would need me to reverse the extruder motor (due to the handedness of the drive assembly required to clear the mounting bracket). I did succeed in making a backup using AVRDUDE and a PICkit 2.

Edit: The Arduino 'bumper' is usable - a bit tight, so either my X and/or Y scaling is fractionally off or the Elegoo Mega2560 clone PCB is fractionally oversize.

17 Jan 2022 - Running my own Marlin build and finding/fixing more mechanical defects

Progress of a sort on the CTC DiY I3 3D printer . . .

The stock firmware is fairly sucky, probably doesn't have thermal runaway protection, and CTC don't appear to have released their source :( so I've been working on configuring a Marlin 1.1.9 build to run on it. Its only got an ATmega1284P (which has 128K Flash program memory), and I'm currently at 95% used, so Marlin 2.0.x isn't really a good option as I'd have to pare it down too much. Unfortunately those who have been there before me had a DiY I3 with a different controller so its been a fight to hack the config files into a usable state for it. I've still got some FUBARed Z motion defaults I need to sort put before it tries to get the Z axis to dig for Australia again! Maybe I should restore the backup of the original firmware and time some motions . . .

In other news, there is supposedly no calibration table for its thermistors that's usably close, so I've had to generate one fudged from an Excel spreadsheet and some dodgy temperature measurements taken with a 1N914 diode stuffed up the hot end
My life was complicated here by the lack of any thermometer that could survive hot end temperatures.

Bed Levelling needs some work, I'm trying to get manual mesh levelling up and running but it really *HATES* concave beds, as there is no option to automate moving to a safe height to clear the edge after homing off the edge of the bed. Various kludgy firmware hacks have been proposed, but I think a hardware hack is in order - use the Ymin limit switch to switch in a different height Zmin limit switch when its not over the bed, so it can be adjusted to home at a height that skims just clear of the [0,0] bed corner, then can go -Z by up to a mm or so before the regular Zmin limit trips, to allow it to level mesh points 'in the valley' without a Z probe.

To that end, has anyone got a *looooooooong* lever SPDT microswitch hanging about? Flat lever and 20mm 2 hole body with terminals on the bottom preferred. Also, ideas for a cheap-skate Z probe wouldn't go amiss.

In the end I found some suitable switches on Amazon and built my dual switch Z axis limit 'Z-hop' mod. It fits in place of the original switch and if homing, with the nozzle just off the front of the bed provides a Z limit a little over 0.5mm higher than that over the bed, with the difference adjustable by bending the long switch lever. Some months later I found a BLtouch Z probe clone far cheaper than I could build any sort of deployable probe.

Also, has anyone got experience automating acquiring temperature calibration table data for Marlin? I'm thinking maybe a Type K thermocouple bonded into a knackered brass extruder nozzle with high temperature cement, and some sort of PC interface for it, talking to Marlin with M105 SHOW_TEMP_ADC_VALUES enabled. Take it up in steps, reading the ADC and temperature for each till its good & hot, then log the cooling curve and check it matches reasonably well, and finally spit out a table in Marlin header file format.

  • CAUTION: Belt tensioners destroy themselves!

The idiots at CTC used D shaft offcuts for the belt tensioner pully shafts and used the drive type pully for the idlers so the shaft turns with the pully. Running in a plastic hole with no bushing it acts as a D reamer and tries to chew its way back to the motor! A reasonable bodge fix is to flatten four M5 split washers (two for each tensioner), and wedge them in the recesses either side of the tensioner body, with the splits towards the tension screw. That's steel on steel, but if kept greased is better than steel D reamer on plastic! Long term it needs decent ball bearing tensioners. See below.

20 Jan 2022 - Flexible Z screw couplers

The original rigid couplers between the Z stepper motors and the Z screws were unsatisfactory, as any misalignment directly pushed the gantry laterally resulting in prints with pronounced Z banding. I therefore bought some helical flexible couplers for coupling 5mm to 8mm shafts, and installed them with a 7mm ball bearing inside each to transfer the axial thrust loading from the Z screws direct to the motor shaft to minimize Z bounce. I had to shim the lead screws (which are ordinary M8 allthread) with aluminum cut from a drink can to get them concentric in the 8mm end of the coupler as their OD is slightly undersize.

Although there was a notable improvement in print quality once I had carefully adjusted the coupler alignment, it wasn't a total cure as the lead screws are still shimmying enough to wobble the gentry at low Z heights. I need to decouple the drive nuts from the gantry, by flipping them the other way up and adding a thrust bearing that doesn't constrain them radially between them and the gantry. The nuts will also require anti-spin arms, and as the screws will no longer have any constraint above the couplers, they'll need top bearings.

I also added a silicone 'sock' over the hotend to improve its insulation and reduce the hot touch hazard to just the nozzle itself.

10 Feb 2022 - Upgrades

CTC DiY I3 3D printer progress: All slider bushings have been replaced with real linear bearings and I'm now printing a 3DBenchy in black PLA on 1.8mm glass (cut from a broken picture frame), with cooling*, using Cura 3's 'stock' slicer settings: Fine (0.1mm layers, 20% infill). So far its looking good.

I need to do something about a proper enclosure for it as the ambient temperature is a bit on the low side.
Currently its in a cardboard enclosure made from a very large cardboard Amazon box, with a thin plastic sheet curtain front. This is a fire risk, and replacement with a non-combustible enclosure (e.g. made from plaster wallboard) or flame-retardant enclosure should be a high priority. Unfortunately running without an enclosure isn't a good option due to the number of print failures I've had due to warping caused by drafts resulting in loss of bed adhesion.

* I added a 50mm centrifugal part cooling fan, stuck onto the back of the extruder motor using 3M (clone) VHB tape, with a thin aluminum tapered duct aiming at the extruder nozzle. This fan is connected to the only software controlled fan port on the Anet3D controller - FAN1. (FAN2 is permanent 12V, used for controller board cooling.) The extruder cooling fan is now wired in parallel to the hot-end heater. ToDo: design and build an extruder fan run-on circuit so sit starts when the heater is first activated, then continues to run to keep the top of the heat-break cool till the hot-end is below 100°C (or maybe simply a retriggerable timer of several minutes).'

13 Feb 2022 - Running out of program memory!

I just managed to build Marlin v1.1.9 with UBL (unified bed levelling) to fit in a ATmega1284P (ANET 3D v1.5 board).

Will I be using it? That's a hard *NO* because to get it to fit I had to disable just about everything else except thermal protection and minimal LCD menus. No SD support, no emergency parser, no cold extrusion prevention, no endstop interrupts, no G26 mesh validation print, no M503 and a host of other minor snips and vicious GCC size optimizations. I even rewrote the Arduino LiquidCrystal library with no 8 bit support to save another hundred bytes. Also it wont fit with *any* bootloader so the only option would be to use an AVR programmer and ISP. :(

Ian B: Seems that the ANET 3D board is seriously under-spec with that processor. It wouldn't have cost them much to fit a processor with bigger ROM.
Anyway, some say UBL is all it's cracked up to be. Just get your build plate physically level, as I'm sure you have.
(I suspect Ian B meant: "... UBL isn't all it's cracked up to be.")

Petr Cecil: Check the bigtreetech boards on the AliExpress I had one for about 12 quids in some sale, still running on it my ender 3
They got much more memory

16 Feb 2022 - More musings on bed levelling and program memory

I was just looking at my options before building a Z probe. I've already got manual bed levelling with a 5x5 grid installed without disabling SD support or anything else nice to have, so I've just got to look at alternatives to full UBL. e.g. switch (from UBL) to AUTO_BED_LEVELING_BILINEAR with no other changes and it goes from needing 100% + 410 bytes more (than optiboot max user progmem) to only 62%, so I should be able to turn SD support back on + most of the nice stuff I pruned. Although a more capable controller would be *nice*, this *IS* only a £99 3D printer so its hard to justify spending for a good controller before I've even got all the mechanicals up to scratch.

My 3D printer build was then on hiatus for several months. I did do a couple of non-notable successful prints on its (questionably) manually leveled bed, and spent a fair bit of time teaching myself OpenSCAD.

18 June 2022 - Upgrading the belt tensioners with ball bearings


  • CAUTION: Belt tensioners' destroy themselves!

The idiots at CTC used D shaft offcuts for the belt tensioner pully shafts and used the drive type pully for the idlers so the shaft turns with the pully. Running in a plastic hole with no bushing it acts as a D reamer and tries to chew its way back to the motor! A reasonable bodge fix is to flatten four M5 split washers (two for each tensioner), and wedge them in the recesses either side of the tensioner body, with the splits towards the tension screw. That's steel on steel, but if kept greased is better than steel D reamer on plastic! Long term it needs decent ball bearing tensioners.

Ref: 17 Jan 2022 - finding/fixing more mechanical defects

Belt Tensioner

Well I finally got and fitted MR85ZZ ball bearings to both belt tensioners on my CTC DiY I3 3D printer. The bearings are ludicrously tiny, 8mm OD, 5mm ID and only 2.5mm thick, which is only 1.5mm radially for both races and the balls between them, but that's what it takes to fit the bearing recess either side of CTC's 'factory' belt tensioner. Each bearing is held in its seat by a M3 screw next to the outer race, so they aren't going anywhere. I loctited the D shaft into the front X tensioner bearing so I shouldn't have any more failed prints due to it walking out of the idler pully.

For anyone else contemplating the Zuhai CTC DiY I3, I couldn't find a STL (or any other model) of the tensioner anywhere, which as supplied is a wear part, and a rapidly wearing one at that, as the D shaft will chew the holes badly out of round in only a few hours printing unless you mod it so it isn't running edged steel on plastic, so (as usual) I modelled it in OpenSCAD, taking the dimensions as accurately as I could from the 'factory' tensioner. Get the tensioner model here: File:Tensioner4.zip

25 June 2022 - Testing a BLtouch probe

I'm (slowly) working on adding auto bed levelling to my CTC DiY I3 3D printer.
Here's an Arduino sketch to bench test a BLtouch/3Dtouch (or clone) levelling sensor, that lets you set probe states by single letter serial commands and reports the ZMIN output status, like this:

*** BLtouch/3Dtouch probe tester ***
D = Deploy
T = Tswitch
R = Retract
S = Self test
A = Alarm off
? = read ZMIN
The Arduino LED echoes the ZMIN state, ON=High / OFF=Low
ZMIN is Low (0.10V)
ZMIN is High (5.00V)

The sketch: File:BLtouch tester.zip

29 June 2022 - Mounting the BLtouch, and building Marlin to support it

Slight progress on adding a BLtouch (clone) ABL sensor to my Zuhai CTC DiY I3, 3D printer. I've got the probe bracket printed and the BLtouch mounted on my printhead, with only 26mm Y offset, and nearly no X offset, without blocking access to the top of the throat in case of filament problems.

I drilled two 3mm holes just in from the front edge of the L bracket that holds the print head assembly to the X gantry carriage, in front of the mounting block that holds the hotend, to fix the bracket to with 2.5mm self-tappers from underneath into the printed probe bracket. My bracket was a little too low for the optimum probe height relative to the nozzle tip (above the tip by half the probe extension), so I ended up shimming it with a piece of wooden coffee stirrer. Once I touched it in with a black marker, you wouldn't know the shim is there, so although I fixed my OpenSCAD' bracket model, I'm going to be lazy/frugal and not re-printt it'

My printer uses an ANET3D v1.5 controller, so I've only got 128K FLASH on the ATmega1284P MCU to play with (half that on the usual ATmega2560 based boards), which has made building Marlin 1.1.9 small enough to fit with AUTO_BED_LEVELING_BILINEAR and BLTOUCH enabled quite a challenge.
Even with aggressive GCC optimizations, (see links section below) it didn't quite fit until I disabled the boot screen. It was a choice between that and ditching Optiboot. :(

Sketch uses 129932 bytes (99%) of program storage space. Maximum is 130048 bytes.

Its a 'full fat' Marlin v1.1.9, with full menu, SD support and all the other nice to have goodies enabled., and I've still got 116 bytes left for any tweaks I want to add! 😁

Petr Cecil: Just keep important features like thermal runaway protection on in marlin so you don't burn your home :))

Yes, keeping thermal runaway protection was my highest priority. Without it, you are one loose screw away from a house fire! Many thanks to Petr for letting me use his crimper and JST connector parts to make up a JST XH-3 cable I badly needed for my BLtouch install. For anyone else needing JST XH (and duPont) crimping capability, here's what Petr recommends: https://www.amazon.co.uk/gp/product/B07VX6YGQ8/ and having used it, I would also recommend it.

1 July 2022 - Wiring the BLtouch probe

I've got most of the recabling done on my CTC DiY I3 for the BLtouch probe. I've spliced a three wire breakout cable for +5V Gnd and servo signal into my display ribbon cable, and re-done the loom to the printhead to add the BLtouch extension cables. All that's left to do is assemble the adapter board that Petr helped me with the JST cable for, mount and wire it, flash a BLtouch enabled Marlin build, and then I'll need to calibrate the Z offset.

... and here's the circuit I intend to use to combine use of the regular limit switch which is set up to inhibit Z movement approx half a mm below the bed surface (less than the flex in the gantry) so it cant 'dig for Australia' if for any reason the BLtouch wasn't deployed before homing.

I constructed the combiner board on Veroboard, laying it out using VeeCAD, from the schematic I drew up in TinyCAD, mounted it to the printer and wired it up.

5 July 2022 - Visualizing the bed levelling mesh

Meanwhile, I've been futzing around with visualising 3D printer bed levelling meshes from Pronterface *without* pasting the M420 V mesh data into a website. Marlin comes with an OpenSCAD mesh visualiser called MarlinMesh.scad, and it turns out that all you need to do to get external mesh data into that is to pass it in on the OpenSCAD command line as variables defined by -D override variables with file scope defined in the file.

The prerequisites for using it are explained here, but if you've already got OpenSCAD installed and are using mesh bed levelling, you'll only need to skim this: https://3dwork.io/en/visualize-3d-mesh/

To do this from Pronterface, with a hard coded mesh, as I hadn't figured out the M420 mesh parsing yet, put MarlinMesh.scad in the printrun directory and (on windows) in Pronterface send:

!os.system('start /max "" "C:\Program Files\OpenSCAD\openscad.exe"  MarlinMesh.scad -D $vpd=800 -D measured_z= 

Note that this is currently Windows only, as the os.system() command string to launch OpenSCAD and return immediately:

'start /max "" "C:\Program Files\OpenSCAD\openscad.exe" '

will be very different under LINUX or OSX. The rest of the command line should be the same.

Also I would strongly recommend editing the default mesh in MarlinMesh.scad (lines 24-30) to be a minimal 'null' mesh:

  measured_z=[[0,0],[0,0]]; //minimal mesh

to make it obvious if your mesh data hasn't been passed in successfully.

ToDo: Write a script to send G420 V to the printer and parse the returned mesh data into a string containing the mesh in the above OpenScad list of lists format, that can simply be appended to the os.system() command line after the -D measured_z=

Later that evening:
I've written and tested the Pronterface macro to launch MarlinMesh.scad from Pronterface with the printer's current MBL mesh from a M420 V report of the form:

Bilinear Leveling Grid:
      0      1      2      3      4      5      6
 0 -0.086 -0.045 -0.037 -0.046 -0.167 -0.292 -0.421
 1 +0.034 +0.038 -0.002 +0.017 -0.017 -0.121 -0.413
 2 +0.122 +0.098 +0.162 +0.034 -0.069 -0.234 -0.472
 3 +0.205 +0.196 +0.120 +0.071 -0.007 -0.149 -0.467
 4 +0.175 +0.174 +0.102 +0.010 -0.130 -0.313 -0.587
 5 +0.194 +0.189 +0.116 +0.034 -0.042 -0.170 -0.568
 6 +0.128 +0.089 +0.032 -0.033 -0.168 -0.373 -0.594
echo:Bed Leveling Off
echo:Fade Height Off
My poor bed looks like a map of the Himalayas!

So I've now got a Pronterface button that visualizes my bed live, without resorting to an online bed visualizer WWW site. 😁

Even with ABL enabled, its useful to let you see if your whole bed is out of whack' and could benefit from adjusting its levelling screws to reduce the range of Z offsets the ABL has to compensate for.

It is currently Win x64 only, as the command line to launch OpenSCAD is OS specific. It shouldn't be hard to change that for Linux or OSX.

To add it to your own Pronterface, first put MarlinMesh.scad in your Printrun folder, then paste the following into a new Pronterface macro:

!################# Bed Visulization macro #################
!# Pronterface script to invoke OpenSCAD MarlinMesh with  #
!# the current MBL mesh returned by M420 V.               #
!#                                                        #
!# (c) Ian.M 7/7/2022                                     #
!#                                                        #
!# "THE BEER-WARE LICENSE" (Revision 42):                 #
!# "Ian.M" <https://t.me/Ian_M_2019> wrote this stuff.    #
!# As long as you retain this notice you can do whatever  #
!# you want with this stuff.  If we meet some day, and    #
!# you think this stuff is worth it, you can buy me a     #
!# beer in return.     Ian.M                              #
!import time
!import os
M420 V ; requst ML grid
!time.sleep(1)		# wait for it
!idx=len(self.p.log)-1 	# get last line in log buffer
!idxf=None		# error value 		
!for x in range(idx,max(idx-20,0),-1):	# iterate backwards 
!  if self.p.log[x].find("Grid:")>8:	# looking for 'Grid:', if found:
!    idxf=x+2				# set idxf to first (real) line of grid	
!    break;				# and exit loop
!  if self.p.log[x].find("echo:")==0:  # looking for 'echo:', if found:
!    idxl=x-1				# set idxl to previous line till last line of grid is found
!#print("Debug: range "+str(idxf)+", "+str(idxl))
!if (idxf is None) or (idxl is None):	# M420 failed
!  self.logError("Error: M420 failed")
!  return
!if idxf>idxl:	# M420 no grid
!  self.logError("Error: M420 did not return a grid")
!  return
!for x in range(idxf,idxl+1): # build list of OpenScad lists
!  mesh=mesh+"["+str(self.p.log[x])[3:].rstrip().replace(" ",",")+"]"	# build comma separated list
!  if x<idxl:
!    mesh=mesh+"," # more to follow
!  else:
!    mesh=mesh+"]" # last one - end outer list
!# Build MMcmd for OpenSCAD installed in default location on 64 bit Windows.
!# N.B use explicit 64 bit Program Files directory as Pronterface is a 32 bit application,
!# so %ProgramFiles% returns %ProgramFiles(x86)%, which is the wrong folder.
!MMcmd='start /max "" "%ProgramW6432%\\OpenSCAD\\OpenSCAD.exe" ' # change this OS dependent stuff!
!MMparams="MarlinMesh.scad -D $vpd=800 -D measured_z=" # OpenSCAD command line parameters
!# n.b. MarlinMesh.scad must be in printrun working directory
!# -D defines an OpenSCAD constant for the session, overriding variables within the file. 
!print("Invoking MarlinMesh.scad with this mesh.")
!print("Exec: "+MMcmd+MMparams+mesh)
!os.system(MMcmd+MMparams+mesh) #Execute it

Edit: It turns out, that depending on your Pronterface version, you'll probably need to import os and time at the top of the macro. I've added them above.

10 Sept 2022 - Z-screw wobble isolation

Back in January I wrote:

The original rigid couplers between the Z stepper motors and the Z screws were unsatisfactory, as any misalignment directly pushed the gantry laterally resulting in prints with pronounced Z banding. I therefore bought some helical flexible couplers for coupling 5mm to 8mm shafts, and installed them with a 7mm ball bearing inside each to transfer the axial thrust loading from the Z screws direct to the motor shaft to minimize Z bounce. I had to shim the lead screws (which are ordinary M8 allthread) with aluminum cut from a drink can to get them concentric in the 8mm end of the coupler as their OD is slightly undersize.

Although there was a notable improvement in print quality once I had carefully adjusted the coupler alignment, it wasn't a total cure as the lead screws are still shimmying enough to wobble the gentry at low Z heights. I need to decouple the drive nuts from the gantry, by flipping them the other way up and adding a thrust bearing that doesn't constrain them radially between them and the gantry. The nuts will also require anti-spin arms, and as the screws will no longer have any constraint above the couplers, they'll need top bearings.

At long last, I've completed the next stage of this, by laser cutting new top brackets and bearing retainers for 688ZZ ball bearings (8mm ID, 16mm OD, 5mm wide) from plywood, consisting of a redesigned bracket in 5mm ply, with a 16mm hole for the bearing which fits flush, surrounded by six tiny holes to fix retaining rings cut from 3mm ply above and below the bracket, each held by three tiny 2mm screws. I also laser cut the anti-spin arms for the Z-nuts from 5mm black Acrylic. All ply parts were spay painted matte black to match the rest of the printer frame. A Thursday evening well spent.

I installed the parts and after some fiddling around managed to reduce the Z-screw runout, and got the screw centered well enough in the gantry end nut mounts not to touch and jerk. I still haven't got proper thrust bearings, and am making do with a stack of three M10 washers on the long end of each Z-nut, which have *NOT* been flipped as originally planned, as it looks like I'll need something other than the Z-screw to loosely constrain the thrust bearing. The washers are lightly greased so can slide over each other fairly readily

After re-leveling (and some BLtouch calibration issues that were borking my first layer height), I finally managed to print a good test cube. Its got much less pronounced Z banding than before this upgrade. Hopefully adding ball thrust bearings will eliminate most of the residual banding. ToDo: design & fabricate cages for these bearings. The problem is a lack of space - I haven't got a lot of height between the top of the coupler and the bottom of the nut, and also, anything much larger than the 22mm OD of the nut flange would force me to move the part cooling fan and redesign its duct.

OpenSCAD design files and photos to follow

06 January 2023

Another hiatus - I didn't need to do any 3D printing and was busy learning the RML mini-lathe. However I've made a small but significant improvement to the Z axis with nothing more than a few square cm of waxed paper! I took the backing paper off some double-sided tape, and wrapped one turn of the paper round the Z screw to make a spacer to fit inside the stack of washers. It sits over the lip on the end of the nut, inside the ID of the washer stack and helps the washer stack stay centered on the screw so none of them touch the screw, catch and jerk, but is so flimsy that the washers can still slide laterally with minimal extra force on the X gantry. A test cube showed much reduced Z banding vs the previous one from October.

Its still not good enough as there is far too much runout at the bottom of the right-hand lead-screw which is shifting the X gantry support force to and fro enough to wobble it. Either I've got a bad coupler, its poorly assembled or there is a kink in the end of the screw where it was cut. Probably the best option will be to chuck the leadscrew in a soft collet in the lathe, get it running true, then turn the thread off the end of the leadscrew, shrink on a short bored out piece of steel rod, then turn that to 8.00 mm diameter, concentric to the screw, so I'm no longer trying to clamp on the threaded end.

- more to follow -

Some useful links

  • https://github.com/ralf-e/ANET-3D-Board-V1.0 - Schematic for an earlier version of the controller, near enough the same as the v1.5, and for the LCD2004 display/buttons board. Note that connector pinouts should be checked against the actual board before trusting them. e.g. I know the end stop connectors have pins 1 and 3 swapped vs the schematic.
  • http://lokspace.eu/anet-a8-wifi-mod/ - How to add printing over WiFi using an ESP-01 ESP8266 WiFi module and esp-link, by populating the Anet3D 'USB BLE' header + removing two zero ohm resistors. Level shifting is needed to get the 5V level ATmega TX pin down to 3.3V levels for the ESP8266 RX pin, hence the resistors on the carrier board. There's also no need for a USB UART adapter to flash the ESP8266, as the ANET main board has one of those. After dong the mainboard mod, simply take two short duPont F-F jumpers and link opposite corner pins of J8 the 'USB BLE' header, and use the mainboard's USB port. After flashing, remove the duPont wires, fit two jumper caps in the BLE position, and carry on with esp-link setup. Alternatively, use a Wemos D1 Mini clone which has all you need on-board except the level shifter, and its simple enough to solder two resistors for that. See my page WiFi 'tethered' Arduino robot