Author:


DIY Refurbishing your espresso machine

Posted by on May 16, 2013

Leaky head?, Low flow rate?, read on…

Most of mid to low end espresso machines share pretty much the same pump and block assembly with very few differences, there are in fact just a few major designs out there most of which are aluminum/brass based and manufactured in China, however that doesn’t neccesarily make them bad.

In all inexpensive units (and some expensive units sold as “professional” but they’re actually a product of marketing bullcrap) the group head has a spring valve that opens when enough pressure builds on the head, this happens when the pump is turned on and it’s there to prevent water leakage. Some better units will use solenoid valves instead, which also allow to set the flow rate in some cases.

The passive valves used on inexpensive units require a clean surface to sit on, much like an engine valve does. The reason espresso heads can leak is simply because of an uneven mating surface (dirty valve seat or dirty valve) it doesn’t have to be a faulty part so if your machine leaks, don’t assume you’ll need rare / expensive spare parts to fix it. If you’ve taken good care of your unit chances are it needs a slight clean up and polish.

Like I said, this gparticular uide is mostly for inexpensive machines, I don’t have experience with high-end units as I’ve never had the pleasure to work with them.

 

Alright, bring it on!

To proceed, remove the water reservoir, portafilter and any loose parts such as filters, trays, etc. Tip the unit over, I use bubblewrap on the countertop to prevent scratches. In my case I had to remove the bottom cover (plated steel) which was held in place with 4 security torx screws.

Identify the type of head/block assembly, mine has a 12MM nut which holds the diffuser and forms part of the valve assembly itself. Other heads may use a notched nut or similar assembly allowing for a flat-head screwdriver to be used. Go ahead and remove it.

diy_espresso_head_before

A view into the brew head before cleaning it, you can clearly see it’s become obstructred. The valve was in even worse shape!

The valve is often spring loaded and has a silicone seal / head. This is where some of the sediment build-up occurs and prevents it from sealing the boiler properly. But most of the build-up occurs on the valve body, which is often (but not always) brass, on more expensive units you may also find stainless steel parts.

Once you’ve removed the nut pull out the spring if it didn’t come out on it’s own, now that the entire valve assembly has been taken apart, use a flashlight to look into the valve body, you’ll probably find the opening to the boiler is slightly (or severely) restricted with build-up.

If there’s no way to remove the bottom of the unit, you’ll need to work with a mirror to look into the boiler.

diy_espresso_head_valve

Valve assembly after clean-up.

To proceed with the clean-up of the valve body you’ll want to use ~300 grit sandpaper (emery cloth) and then 600 to finish off. You could use your Dremel / rotary tool with a fine brush attachment used for polishing brass (don’t use any compounds, just water) but you have to be very careful not to damage the threads or the valve seat, if you increase the original diameter there’s a chance the valve could pop in and float inside the boiler, allowing all of the boiler contents to spew out and it would never seal again forcing you to replace the entire valve head which may end up costing quite a bit of money and may not even be worth it on inexpensive units. Another possibility is for the bulb to catch and get stuck, so beware of the Dremel and abrasive tools.

 

After cleaning and polishing, it looks brand new!

After cleaning and polishing, it looks brand new!

If you want to make sure all the surfaces are neatly cleaned up and polished, you can use an old lead pencil as a former to wrap a piece of sandpaper around, tapering the top into a cone and then inserting it inside the valve body (with water) you’d proceed by twisting it a few times, removing it, inserting some cloth or paper towel wrapped around to clean up the valve and then take a look inside with a flashlight, repeat until it’s all nice and polished, specially the valve seat.

The silicone valve in my case had a lot of build-up but was easily removed by hand, don’t use any abrasives on it and try not to scratch it in any way.

Now that you’ve cleaned it all up, go ahead and add some water with the unit standing on it’s usual position and give it a few flushes, any loose pieces of build-up should come out, as well as anything you’ve unwillingly introduced while cleaning and polishing the valve body.

 

This is how the assembly goes, valve bulb/head pointing up.

This is how the assembly goes, valve bulb/head pointing up.

If all looks good, go ahead and assemble the valve back to it’s original state. The silicone valve goes facing up into the valve seat, make sure the spring is nice and clean as well as the silicone valve head. If you see any damage on the silicone it’s time to replace the valve or come up with a makeshift solution…

Once it’s all assembled, torque the nut down making sure your diffuser disc / plate is in the right position and turn the unit on, give it a nice flush.

 

In my case the diffuser was slightly blocked so I had to clean it up with a needle and lots of patience before I installed it, This procedure made heaps of difference. Basically my espresso was not only leaky but also had low flow rate and it sputtered a lot making it difficult to obtain a straight shot with good crema.

 

Next in my list would be to access the pump to see if there’s a pressure relief adjustment and go ahead to calibrate it up to 9BAR at the head, that however is going to be a whole ‘notha quest for me. In that event I may probably end up refurbishing the pump as well.

 

Hopefully this guide has been of use to you!
And as you know, don’t send your machine to the store… A good barista fixes his/her own espresso!

 

Have a good one,
Gus

UT61E Protocol Description

Posted by on March 18, 2013

Intro:

The protocol used by the UT61e is quite simple, each packet contains 14 bytes. It constantly streams packets as the screen is updated at around 2 packets a second. The 14 bytes are basically a string where the range, digits, function, status are contained.

The serial interface settings are:

19200 baud, odd parity, 7 data bits, 1 stop bit, no handshake.

Describing the protocol:

This snippet shows you how the data is separated, I handle the 14 bytes as a string, which simplifies the process of separating each portion and since this is a low sampling rate application with low priority, it’s not a resource hog.

If ReadSerialPortData( port, @inp, 14 )
 
	If AddElement( *this\sample() )
		*this\sample()\range 		= Asc(Mid(inp,  1))  ; RANGE
		*this\sample()\digits		= Mid( inp, 2,  5 )  ; DIGITS
		*this\sample()\function 	= Asc(Mid(inp,  7 )) ; FUNCTION
		*this\sample()\status		= Asc(Mid(inp,  8 )) ; STATUS
 
		*this\sample()\option[0]	= Asc(Mid(inp,  9 )) ; OPTION 1
		*this\sample()\option[1]	= Asc(Mid(inp, 10 )) ; OPTION 2
		*this\sample()\option[2]	= Asc(Mid(inp, 11 )) ; OPTION 2
	EndIf
 
EndIf

I believe the last two digits are the “end of packet” limiter (CRLF) however I currently cannot test this, I wrote the code a long time ago and I forgot to comment on this slight detail, but as you can see I’ve defined the CRLF contants, so it must be there.

A list of constants:

Here are some constants from my UT61e (unpublished) library…

#FUNCTION_VOLTAGE 		= %0111011
#FUNCTION_AUTO_CURRENT_UA 	= %0111101
#FUNCTION_AUTO_CURRENT_MA 	= %0111111
#FUNCTION_CURRENT_22A		= %0110000
#FUNCTION_CURRENT_MANUAL_A	= %0111001
#FUNCTION_OHMS			= %0110011 
#FUNCTION_CONTINUITY		= %0110101
#FUNCTION_DIODE			= %0110001 
#FUNCTION_FREQUENCY		= %0110010
#FUNCTION_CAPACITANCE		= %0110110
#FUNCTION_TEMPERATURE		= %0110100
#FUNCTION_ADP			= %0111110
 
#RANGE_ONE			= %0110000 ; Example: 22.000nF
#RANGE_TWO			= %0110001 ; Example: 220.00nF
#RANGE_THREE			= %0110010 ; Example: 2.2000µF
#RANGE_FOUR			= %0110011 ; Example: 22.000µF
#RANGE_FIVE			= %0110100 ; Example: 220.00µF
#RANGE_SIX			= %0110101 ; Example: 2.2000mF
#RANGE_SEVEN			= %0110110 ; Example: 22.000mF	
#RANGE_EIGHT			= %0110111 ; Example: 220.00mF
 
#DIGIT_0			= %0110000
#DIGIT_1			= %0110001
#DIGIT_2			= %0110010
#DIGIT_3			= %0110011
#DIGIT_4			= %0110100
#DIGIT_5			= %0110101
#DIGIT_6			= %0110110 
#DIGIT_7			= %0110111 
#DIGIT_8			= %0111000
#DIGIT_9			= %0111001
 
#STATUS_OL			= 1 < < 0
#STATUS_BATT			= 1 << 1
#STATUS_SIGN			= 1 << 2
#STATUS_JUDGE			= 1 << 3
 
#OPTION1_RMR			= 1 << 0
#OPTION1_REL			= 1 << 1
#OPTION1_MIN			= 1 << 2
#OPTION1_MAX			= 1 << 3
 
#OPTION2_0			= 1 << 0
#OPTION2_PMIN			= 1 << 1
#OPTION2_PMAX			= 1 << 2
#OPTION2_UL			= 1 << 3
 
#OPTION3_VAHZ			= 1 << 0
#OPTION3_AUTO			= 1 << 1
#OPTION3_AC			= 1 << 2
#OPTION3_DC			= 1 << 3
 
#UT_CR				= %0001101
#UT_LF				= %0001010

That’s all for now, I currently don’t have a serial interface to test with (Ain’t got the USB cable either) so I can’t finish the library as to post it, but hopefully I’ll get it done eventually.

The supplied software by UNI-T is pretty bad and it’s Windows only, hence the drive to write my own.

As it is, it should give someone a head-start if they’re about to write their own front-end. On the datasheet of the UT61e controller it’s all explained in fine detail, but I can’t recall the number at the moment.

This whole thing was part of a bigger picture, but I had to give up the concept due to lack of funding.

Alright, enough of this shoulda, coulda, woulda!

Cheers,
Gus

(PB) Loading CSV directly to a Hash Map

Posted by on February 21, 2013

When dealing with string maps, being able to easily load them from a file is a must. For example take language files for different local translations. The simplest, cleanest format would be CSV. The ideal data structure? — A hash map.

While trivial, this code will come in handy for many other things!

EnableExplicit
#CSV_QUOTE 	= "'"
#CSV_SEPARATOR 	= ","
 
Procedure IsEvenNumber(N)
   ProcedureReturn ( 1 - 1 & N )
EndProcedure
 
Procedure IsOddNumber(N)
   ProcedureReturn ( 1 & N )
EndProcedure 
 
Procedure.s RemoveQuotes( String.s )
 
	If Left(String, 1) = #CSV_QUOTE
		String = Mid( String, 2 )
	EndIf
	If Right(String, 1) = #CSV_QUOTE
		String = Left( String, Len(String) - 1 )
	EndIf
 
	ProcedureReturn String
EndProcedure
 
Procedure.i LoadStringMap( FileName.s, Map StringMap.s() )
	; escaping of quotes is currently not supported
	; if an uneven number of quotes is found on a line, the line is ignored.
 
	Define.i fp = ReadFile( #PB_Any, FileName )
	If IsFile(fp)
 
		While Not Eof(fp)
 
			Define.s line = Trim(ReadString( fp ))
			If line
				If CountString( line, #CSV_SEPARATOR ) => 1
 
					Define.i quote_count = CountString( line, #CSV_QUOTE )
					If IsEvenNumber( quote_count )
 
						Define.s key		= RemoveQuotes( StringField( line, 2, #CSV_QUOTE ) ) 
						Define.s content	= RemoveQuotes( StringField( line, 4, #CSV_QUOTE ) )
 
						StringMap( key ) 	= content
 
					EndIf
 
				EndIf
			EndIf
 
		Wend
 
		CloseFile(fp)
		ProcedureReturn MapSize( StringMap() )
	EndIf
 
EndProcedure

Example of data:

'Update', 'Actualizar'
'Databases', 'Bases de datos'
'Program', 'Programa'
'Options', 'Opciones'
'Export', 'Exportar'

Example of use:

NewMap spanish.s()
LoadStringMap( "locale/spanish.csv", spanish() )
 
ForEach spanish()
 
	Debug MapKey(spanish())
	Debug spanish()
 
Next

Couldn’t be easier!
Cheers.

(SQLITE) When duplicate tables are needed…

Posted by on February 5, 2013

Here’s a quick tip if you want to keep a “schema” or “template” table on your database that you’ll then duplicate to populate with arbitrary data. This system works for collection of files where a particular table could represent a specific drive or medium, just as an example of the many uses it can have.

CREATE TABLE 'new_table' AS SELECT * FROM 'schema'; -- where 'schema' is our template table.

This is basic SQL, but if you were to look up how to duplicate a Sqlite table you may come up short if you aren’t aware of standard SQL. As an exercise, here’s how Sqlite interprets the CREATE command.
A few restrictions could be applied to your SELECT statement, this will depend on your particular requirements.

As always, don’t forget to sanitize every input and when possible, remove user interaction altogether from the query — specially during the construction phase.

Cheers

(PB) Using the Thinkpad Accelerometer

Posted by on January 29, 2013

So I recently got a proper Thinkpad and I was wondering how to interface with the accelerometer to obtain data from it. First of all, I had a look around and it seems the ADXL320 is used in most models, it’s a Low Power, 3-Axis ±5 g MEMS Accelerometer manufactured by Analog Devices.

There are, at least on Windows, two possible interfaces. One is through a device manager, the other is directly through a DLL exposed by Lenovo.

I had yet another look around and found a few snippets in C# by Ben Suter. Decided to port the code and give it a go, instead of looking any further. Despite the fact that I had already exported the function names of the DLL (using my good ol’ dllspyr) I just couldn’t bother looking any further. I had to add the z value, since it was originally ignored. Perhaps because previously a mere 2 axis tilt sensor was used?

The other method involves getting a handle of “ShockMgr” with createFile(); setting up by DeviceIoControl(); and then reading through the data. This makes it easier to validate if the “service” is available, because the DLL could be exposed but non functional, for example.

Da codez:

Here’s the preliminary test code, implementing a crude alarm system:

Structure ACCDATA
  status.i
  x.w
  y.w
  z.w
EndStructure
 
Structure SHOCKSTATUS
  status.i
EndStructure
 
Enumeration 
  #SHOCKSTATUS_RUNNING
  #SHOCKSTATUS_STOPPED
  #SHOCKSTATUS_AUTOIGNORE
  #SHOCKSTATUS_UNDEFINED
EndEnumeration
 
Prototype.i pShockproofGetAccelerometerData( *AccData.ACCDATA )
Prototype.i pShockproofGetShockStatus( *ShockStatus.SHOCKSTATUS )
 
 
If OpenLibrary(0, "Sensor.dll")
 
  ShockproofGetAccelerometerData.pShockproofGetAccelerometerData = GetFunction(0, "ShockproofGetAccelerometerData")
  ShockproofGetShockStatus.pShockproofGetShockStatus = GetFunction(0, "ShockproofGetShockStatus")
 
  Define.ACCDATA old_data, new_data
  ShockproofGetAccelerometerData( old_data )
 
  Define.i triggered = #False
  Repeat
 
    Delay(200)
 
    ShockproofGetAccelerometerData( new_data )
 
    If Not CompareMemory( old_data, new_data, SizeOf(ACCDATA) ) Or triggered
      triggered = #True
      Beep_(1000, 1000)
    EndIf
 
  ForEver
 
  CloseLibrary(0)
EndIf

The status code is interpreted by another function, which I’m not using at the moment but the author had guessed the threshold values and addressed a name for each, from the known possible states exposed by Lenovo.

Procedure.i convertStatusCode( statusCode.i )
 
  If statusCode >= 0 And statusCode < = 4
    ProcedureReturn #SHOCKSTATUS_RUNNING
  ElseIf statusCode = 8 Or statusCode = 9
    ProcedureReturn #SHOCKSTATUS_STOPPED
  ElseIf statusCode = 13
    ProcedureReturn #SHOCKSTATUS_AUTOIGNORE
  Else
    ProcedureReturn #SHOCKSTATUS_UNDEFINED
  EndIf
 
EndProcedure

What now?

I’m going to clean up the code and start making use of this feature, I mean, why not?

As for a proper alarm, you’d have to manage the mute and volume settings plus instead of comparing against the baseline values you’d have to implement a threshold. I’m aware that they’ve issued an application that does exactly this, but I’m not a fan of big resident bloatware — plus where’s the fun in that?

Anyway, that’s all for now!
Cheers.