Friday 1 January 2010

New Year New Plastic

Just over a year ago a friend asked me to make replacement for a broken clip that was part of a light fitting. It was not too difficult to model and I made a copy in ABS with 0.3mm filament, 0.24mm layers.



It did the job mechanically, but with one obvious aesthetic problem: -



The original clips were made from transparent polycarbonate and all I had at the time was green ABS. I didn't use PLA because I worried the lamp could easily get hot enough for the clip to go soft and drop the shade. The only transparent thermoplastic that I could get hold of in filament form was PMMA (AKA acrylic / Perspex, etc), which is available in 1m rods. It is too stiff and brittle to use in my previous extruder, so I promised to have a go when I moved to a pinch wheel design.

The first attempt was a complete failure. It melts at 130 - 140 or 165°C depending where you read. It has a relatively high glass transition, 100-114°C, again depending where you read. I found I could extrude it with a fair amount of force at 180°C. It is very viscous with plenty of die swell. I couldn't get it to stick to anything, including itself, at that temperature though. It isn't sticky like PLA, so it wouldn't stick to masking tape. The obvious second choice was a sheet of acrylic as all thermoplastics will stick to themselves.

The general rule of thumb to make plastic weld to itself is that the average of the temperature of the hot part and the cold part has to be higher than the melting point. So to get it to stick to the base, which is at room temperature it would have to be extruded at twice the melting point minus the ambient temperature. The only plastic that seems to break this rule is PLA which melts at 160°C but will bond to itself at 180°C. I think it is something to do with it having a low glass transition and / or that it is sticky like a glue when it is molten.

I upped the temperature to 240°C but it started to hiss and smoke and still did not bond to the base. Lots of places quote the boiling point of PMMA to be 200°C! I dropped the temperature back to 220°C and it is much happier, but still does not stick .

So the only way to make it bond with itself is to raise the ambient temperature. Cue the heated bed. I set the temperature of my aluminium plate to 100°C, the hottest it can safely be below the glass transition. I taped a small scrap of 3mm acrylic sheet to the middle of the bed with Kapton tape. From my experiments before I estimate the surface temperature would be about 85°C. That gives an interface temperature of about 150°C and that seems to be enough to get it to bond to itself.



Here is a short video of 0.3mm PMMA filament being extruded at 16mm/s: -



Here is the finished object: -



It was not too difficult to release from the bed with a penknife once the bed has cooled that is, I keep forgetting that it is hot! The bed takes ages to cool unless I blow it with a fan.

I am very pleased with the final result. I only had 1 meter of 3mm filament to get this right and I managed to find a suitable bed material, temprature settings and make three clips. The build quality is excellent even if I say it myself.



So another useful material in the RepRap arsenal. Apart from HDPE I think it has the highest working temperature. It is very stiff and brittle though. I had a couple of jams due to it snapping where it enters the extruder barrel. The alignment is not quite right because being so hard it does not press into the worm pulley as far as other plastics. The extruder could do with an adjustment there perhaps, or a bigger entrance to the pipe.

It is a bit more transparent than PLA. It smells a bit more when it is extruded, but it is not an unpleasant smell, I would describe it as sweet and aromatic. The major downside is that it is only available in rod form, so the biggest object you can make in one go is 7 cm3 and at £1.49 per meter on eBay, it is comparatively very expensive.

Hot bed

Making a heated bed to combat warping has been on my "to do" list for a long time. In fact I ordered the materials more than a year ago. My plan was to use an aluminium plate with many small power resistors screwed on the back.

The plate is 8" square to match my table and 6mm thick. A friend with a CNC machine shop kindly machined it for me. It saved me a lot of hard work with a hacksaw and file and looks a lot better as well.



I estimated that it would need about 50W to raise the temperature to 100°C, so I aimed for 100W to give a reasonable margin for control. I used 9 10W 12Ω resistors wired in parallel. Driven from 12V this would take 9A giving a power of 108W.

The holes in the resistors are only big enough for M2 screws. I drilled blind holes and tapped them with a plug tap, actually a broken tapered tap that I ground to a flat end.



Tapping small holes in aluminium is tricky, that was how the tap came to be broken in the first place. The correct size hole for M2 is 1.6mm but I drilled it 1.7mm to make it easier to tap. In fact aluminium is so ductile that the peaks of the thread are still the correct diameter. I.e. the 1.7mm drill would not fit the hole after tapping and the thread was a good tight fit on the bolts. I used paraffin for lubrication.

Soldering the resistors was fun.



I used stout wire to handle 9A and high temperature solder because I fancied using it as a hot plate for soldering. My 50W iron did not have enough power to melt the solder when the resistors were mounted with two thick copper wires leading from them. To get round that I placed it on a silicone matt and powered it up to raise the temperature to 100°C and then soldered it while hot and live, not something I would recommend. As the iron bit is grounded I had to solder all the 0V connections first and then swap the polarity.

The original plan was to power it from a 12V PC power supply and switch it with a big MOSFET. Initial tests with a bench power supply showed it took about 15 minutes to warm up to 80°C. When calculating the power I had forgotten take into account the specific heat capacity of the thick sheet of aluminium. I didn't want to add 15 minutes to the build time, so I decided to double the power. I have abused these resistors before and got away with it. I changed the wiring slightly to make a series parallel combination with a total resistance of 12Ω and fed it from 48V AC giving 192W.

I used a big 350W transformer and controlled the mains to it with a solid state relay. Since the temperature is controlled there is no real point in using a regulated DC supply. It is much more efficient to use AC and avoid the losses associated with rectification and smoothing. It also allows me to use the same control hardware and firmware that I used for the SMT oven.

I made some PEEK insulating stand-offs to mount it on my XY table with a gap of about 6mm below the resistors: -



I wrapped the feed points around two of these to make the transition to a lower temperature with PTFE sleeving before using normal flex to handle the movement of the table.



I also added some foam board to insulate the top of my X-Y table.



This just fills some of the air gap under the plate to prevent air circulating and convecting heat downwards.

I made some PTFE washers to go under the nuts that hold it down by slicing up a failed extruder insulator: -



These deformed considerably when I heated the table to 230°C, highlighting why PTFE insulators fail when used in an extruder.

Here is the final result mounted on the machine: -



I added Kapton tape around the edge as I thought it would stop hot air escaping from underneath, but it didn't seem to make a lot of difference.

Here is the open loop response at full power: -



Although it can reach the required temperature, it is much too slow for SMT soldering. It needs to be able to rise at about 1°C / second for that. So I will stick to using the oven for soldering for now. I was hoping to be able to paste boards, place components and then solder with the board still on the table, but it obviously needs a lot more power.

Here is the response using bang-bang control from the host at one second intervals.



Some analysis: the initial rise rate is about 20°C in 75 seconds. The specific heat capacity of aluminium is 0.9 J /gK and the total weight of the bed plus resistors is 700g. So with 192W the time taken to rise 20°C should be 0.9 × 700 × 20 / 192 = 66 seconds, reasonable agreement as we ignored any heat loss.

The initial fall rate is 5°C in 85 seconds while at a temperature of ~80°C above ambient. So the rate of heat loss is 0.9 * 700 * 5 / 85 = 37W. Looking at the steady state the power is on for about 1 in 6, which would be 32W, so again reasonable agreement.

The plate is ~ 200mm square so its area is 0.04m2 so it looks like we need about 1kw / m2 to reach the sort of temperatures needed for HDPE and probably twice that to have reasonable warm-up time and control. Mendel's build area is also 200mm square, so would require a similar power.

You might have noticed the thermocouple is covered with a piece of ceramic cloth in the photo above. This is what happens if it is just stuck down with Kapton tape:-



You can see that as the temperature rises you get increasing thermal noise. Even with the ceramic cover in place you can see similar noise on the open loop test when the temperature was much higher. I think the reason for this is the convective air currents causing chaotic air turbulence. If you think about it you have hot air rising but, away from the edges, the only way cold air can replace it is by falling through the rising air.

A better place to put the thermocouple would be under the bed to avoid the convection currents, but I wanted to try controlling the surface temperature when it was covered by a bed material. Here is what happens with the thermocouple on top of a 3mm thick sheet of smoked acrylic: -



The set point is 95°C in this case. Clearly a case where bang-bang does not work too well, with 5°C overshoot and 3°C undershoot.

The acrylic loses about 15°C between the bottom and the top surface. That makes it curl upwards, so it would need a frame around the edge to hold it down. Fortunately I have one made from HDPE laminated with aluminium so it should stand the heat. It also adds a significant time lag.

Another problem is that acrylic has a glass transition at about 114°C. When the control was of the top surface temperature, the bottom surface exceeded that during the overshoots and went soft.

So I will need to implement PID for top surface control, but I had a suspicion that a transformer was not going to like PWM into its primary much. Anyhow I put the thermistor back onto the plate and moved the bang-bang control from the PC to the firmware in preparation for building something. Bang-bang was an apt name for what happened next. When the temperature crossed the set point it started dithering the mains on and off. The transformer sounded like it wanted to jump off the desk and then blew its 3A anti-surge mains fuse.

The solid state relay turns the power on at the zero point crossing of the mains, and off when the current is zero. Current builds up slowly through an inductor so what could possibly be wrong? I had noticed big transformers thump when you connect them to the mains, but I had always assumed it was because the secondary usually has a big smoothing capacitor to charge up. However, this was a purely resistive load, and even with no load attached the transformer thumps on start-up, so some reading up on transformer theory was required!

It turns out that transformers take a big surge current and turning on at the zero crossing point is actually the worst point to turn them on. The reason is that when a transformer is running, being an inductor, the current lags behind the voltage by 90°. So normally when the voltage is crossing zero, the current is at its maximum reverse polarity and over the next half cycle of voltage it goes though zero and then to its maximum positive value: -

If the current starts at zero then over the first half cycle it will rise to twice its normal value: -

That would not be too bad except for the fact that transformers usually run with their core close to magnetic saturation for efficiency reasons. That means the core saturates during start-up. The inductance disappears and then the only thing limiting the current is the DC resistance of the primary, about 3.3Ω in my case, so the current can be enormous. Counter intuitively, the best time to turn a transformer on is when the mains is at its peak voltage.

So I learned something I didn't know about transformers. The fix was simple, I added a solid state relay to the secondary circuit and plugged the transformer into the mains. Bang-bang control then was able to pulse it very quickly due to the dithering caused by noise, which ends up with some proportional control, that reduces the temperature swings to a fraction of a degree.



So I can add PID control firmware and it can be shared with my oven control but I have an extra solid state relay and a big transformer. A better solution would be to pick the resistor values to give the correct wattage when wired in series across the mains. Of course mains on a moving table is not the safest design. I would use a heavy three core flex with an earth lead to the plate and a second independent earth strap for safety.

It turns out the first use for my heated bed was not to combat warping, but actually something more essential, details coming soon ...

Tuesday 29 December 2009

Cooking with HydraRaptor

I needed to assemble some PCBs recently, so I set about making a temperature controller for my SMT oven.



First I had to replace the solid state relay on HydraRaptor.



Solid state relays are triacs with an optically coupled input, zero crossing switching and built in snubbers. I used it for controlling a vacuum cleaner when milling. It was massively overrated but for some reason it failed some time ago. I replaced it with a cheaper one and added a varistor across the mains input to kill any transients, as that is the only explanation I can think of for the old one's demise.





The next task was to write a simple graphing program in Python. I tested it by plotting the response of my extruder heater.



With bang-bang control it swings +/- 2°C with a cycle time of about ten seconds.

Here is the code for the graph: -
from Tkinter import *

class Axis:
def __init__(self, min, max, minor, major, scale):
self.scale = scale
self.min = min
self.max = max
self.minor = minor
self.major = major

class Graph:
def __init__(self, xAxis, yAxis):
self.xAxis = xAxis
self.yAxis = yAxis
self.root = Tk()
self.root.title("HydraRaptor")
self.last_x = None
frame = Frame(self.root)
frame.pack()
xmin = xAxis.min * xAxis.scale
xmax = xAxis.max * xAxis.scale
ymin = yAxis.min * yAxis.scale
ymax = yAxis.max * yAxis.scale
width = (xmax - xmin) + 30
height = (ymax - ymin) + 20
#
# X axis
#
self.canvas = Canvas(frame, width = width, height = height, background = "white")
for x in range(xmin, xmax + 1, xAxis.minor * xAxis.scale):
self.canvas.create_line(x, ymin, x, ymax, fill = "grey")
for x in range(xmin, xmax + 1, xAxis.major * xAxis.scale):
self.canvas.create_line(x, ymin, x, ymax, fill = "black")
if x == xmin:
anchor = "nw"
else:
anchor = "n"
self.canvas.create_text((x, ymax), text = x / xAxis.scale, anchor = anchor)
#
# Y axis
#
for y in range(ymin, ymax + 1, yAxis.minor * yAxis.scale):
self.canvas.create_line(xmin, y, xmax, y, fill = "grey")
for y in range(ymin, ymax + 1, yAxis.major * yAxis.scale):
self.canvas.create_line(xmin, y, xmax, y, fill = "black")
if y == ymin:
anchor = "se"
else:
anchor = "e"
self.canvas.create_text((xmin, ymax + ymin - y), text = y / yAxis.scale, anchor = anchor)
self.canvas.pack()
self.canvas.config(scrollregion=self.canvas.bbox(ALL))
self.root.update()

def scaleX(self,x):
return x * self.xAxis.scale

def scaleY(self,y):
axis = self.yAxis;
return (axis.max + axis.min - y) * axis.scale

def plot(self, line, colour = "blue"):
for i in range(len(line) - 1):
self.canvas.create_line(self.scaleX(line[i][0]),
self.scaleY(line[i][1]),
self.scaleX(line[i+1][0]),
self.scaleY(line[i+1][1]), fill = colour)
self.root.update()


def addPoint(self,p, colour="red"):
x = self.scaleX(p[0])
y = self.scaleY(p[1])
if self.last_x != None:
self.canvas.create_line(self.last_x, self.last_y, x, y, fill = colour)
self.last_x = x
self.last_y = y
self.root.update()

def __del__(self):
self.root.mainloop()
The third task was to interface a thermocouple to HydraRaptor. I had a spare analogue input, so I attached one of Zach's thermocouple sensor boards to it. I tested it by attaching the thermocouple to a light bulb with Kapton tape. I then ran a program that turned the bulb on and then off and graphed the temperature response.



As you can see there is a ridiculous amount of noise on the readings. I tracked this down to switching noise on HydraRaptor's 5V rail, which is generated by a simple buck converter from a 24V rail. The AD595 datasheet claims that it has a power supply sensitivity of only 10mV/V so the error should have been a small fraction of a °C. All I can assume is that its rejection of high frequency noise is far less than its DC supply rejection. In fact, pretty much all the supply noise appears on the output.

I fixed it by filtering the supply with a simple RC filter consisting of a 1K series resistor and a 22uF capacitor. I fitted these to the thermocouple board in the unused holes intended for an alarm LED and its series resistor. The power is fed in via the anode connection for the LED. It feeds to the supply rail via the 1K fitted in the R1 position. The positive lead of the capacitor goes into the original +5v connection to the board. The negative lead goes to the GND connection together with the ground lead. This mod will be required whenever the 5V rail comes from a switch mode supply rather than a linear regulator.



Here is the much improved graph with the filter fitted: -



The next thing I tried was bang-bang control of the oven to a fixed temperature with the thermocouple attached to a scrap PCB. No great surprise that there is massive overshoot due to the thermal lag caused by the loose coupling of the PCB to the heating elements via air.



It is obvious some form of proportional control is required, so I implemented PWM control of the mains supply to the oven. As triacs don't turn off until the end of the mains cycle there is no point in varying the pulse width in less than 10ms increments (in the UK). So I implemented a simple firmware scheme where I can specify how many 10ms units to be on for out of a total period, also specified in 10ms units. Setting the period to 1 second allows the heating power to be expressed in 1% units.

My original plan was to implement a PID controller, but after examining the required soldering profile I decided a much simpler scheme would probably perform better.


The is a profile for tin-lead solder that I got from an Altera application note. I mainly use leaded solder at home because the lower melt point gives a much bigger margin for error, it wets and flows a lot better, the fumes are less toxic and it doesn't grow tin whiskers.

Looking at the profile you can see the times are not too critical, but the temperatures are. I reasoned I could simply apply fixed powers to get the right temperature gradient until each target temperature was reached. To get round the overshoot problem I simply measured the overshoot and subtracted it from the target temps.

After a little experimenting I got this profile, which looks pretty good to me: -



The blue line is the target profile, red is actual and the green lines show the time at which each target was reached.

The preheat slope and re-flow slope are simply full power until the temperature is equal to the target minus the overshoot. During the first half of the soak period I had to ramp the power from 0 to 50% to get it to turn the first corner without overshoot. When the reflow peak minus the overshoot is reached I simply turn the oven off. When it gets to the cool section I open the oven door.

Here is the code: -
from Hydra import *
from Graph import *

profile = [(10,20), (120,150), (210,180), (250,210), (330, 180), (420, 20)]

slope = 140.0 / 100
overshoot = 15.0
pre_overshoot = 25

preheat_temp = 150.0
soak_temp = 180.0
soak_time = 90.0
reflow_temp = 210.0
melt_temp = 183.0

preheat_slope = (soak_temp - preheat_temp) / soak_time

s_preheat = 1
s_soak = 2
s_reflow = 3
s_cool = 4

def interp(profile, x):
i = 0
while i < len(profile) - 1 and profile[i + 1][0] < x:
i += 1
if i == len(profile) - 1:
return 0
p0 = profile[i]
p1 = profile[i+1]
return p0[1] + (p1[1]-p0[1]) * (x - p0[0]) / (p1[0] - p0[0])


def oven_cook(profile):
hydra = Hydra(True)
try:
xAxis = Axis(min = 0, max = 500, minor = 5, major = 25, scale = 2)
yAxis = Axis(min = 10, max = 250, minor = 5, major = 20, scale = 2)
graph = Graph(xAxis, yAxis)
graph.plot(profile)

t = 0
state = s_preheat
m_state = s_preheat
hydra.set_mains(100,100)
while t < xAxis.max:
sleep(1)
temp = hydra.get_temperature()
print temp
graph.addPoint((t, temp))
#
# Control the power
#
if state == s_preheat:
if temp >= preheat_temp - pre_overshoot:
hydra.set_mains( 0, 100)
t_soak = t
state = s_soak
elif state == s_soak:
power = (t - t_soak) * 100.0 / soak_time
if power > 50:
power = 50
hydra.set_mains(int(power), 100)
if temp >= soak_temp - overshoot * preheat_slope / slope:
hydra.set_mains(100,100)
state = s_reflow
elif state == s_reflow:
if temp >= reflow_temp - overshoot:
hydra.set_mains(0,100)
state = s_cool
#
# Draw the time lines
#
if m_state == s_preheat:
if temp >= preheat_temp:
graph.plot([(t,10), (t,temp)], "green")
m_state = s_soak
elif m_state == s_soak:
if temp >= melt_temp:
graph.plot([(t,10), (t,temp)], "green")
m_state = s_reflow
elif m_state == s_reflow:
if temp < melt_temp:
graph.plot([(t,10), (t,temp)], "green")
m_state = s_cool

t += 1
hydra.init()

except:
hydra.init()
raise

oven_cook(profile)
This is the first board I soldered with it: -



All the joints were good. I had a few solder balls and some bridging but that was due to not getting the right amount of paste on each pad. I will be working on a solder paste dispenser soon!

I need to do some more testing to see if the arbitrary algorithm will work with large and small boards and with inner planes, etc. It relies on the overshoot being fairly constant, although with leaded solder you have some leeway.

I also want to play with PID to see if I can get a more general solution. The problem I see is that PID does not look into the future, so will always overshoot somewhat, which is exactly what you don't want. I think rather than using the angular profile, that is impossible for the oven to follow, I would have to put in a rounded curve, such as the one the oven actually follows now, as the control input.