cheap etching machine for small pcb’s

posted by on 2012.10.26, under collected, electronics

I quit my last job where I had access to great labs – including the one for making PCBs the easy way (yeah, they have all the nice/expensive tools from Bungard … and a CNC miller/cutter). So now  I had to decide how to setup the needed infrastructure for making PCBs@home. Here are some of the results.

For putting the layout on the PCB I decided to use the direct toner transfer method with a modified laminator like described here. Cause of the chicken-and-egg-problem I used an Arduino to control the heater instead of a dedicated board (what I create after the setup for making PCBs is done so I can create more boards…). It works very well – thanks to all the folks that invented/improved that technology.

Since I do all the fun at home I choose sodium per sulfate as etchant – its a clean and safe solution. First I thought about buying a commercial etching machine. But after some reading it turns out that all the inexpensive and/or cheap machines are … to expensive. I moved to the hardware store and got all I needed for less then 50 euro:

  • round glass vase, 25 cm hight,  9 cm  diameter ~ 5 €
  • aquarium heater, 100 W – 20 €
  • aquarium membrane air pump ~ 10 €
  • fizzy stone ~ 2 €
  • 2 m silicone tube ~ 2 €
  • return valve ~ 3 €
  • a sheet of 4 mm acrylic glass (30 cm x 20 cm) ~ 5 €
  • pack of 4 cupping vessels ~ 2 €

I also ordered a 24 cm long tee thermometer that goes till 110 degree Celsius for ~8 €. But a simple 2-euro window thermometer with a range from -x..50 degree Celsius also does that job. But the tee thermometer looks better. Much!

First I created an holder for the fizzy stone by heating a small strip (5 cm x 10 cm) of the acrylic glass with my kitchen gas torch in the middle and bend it by 90 degrees. Two holes later a cupping vessel and the stone are mounted and put in place on the ground of the vase:

fizzy stone holder

fizzy stone holder

Cause of the air bubbles the etchant could spray out of the upper end. A quadratic cover of 10×10 cm acrylic glass makes a good seal. To keep it in place I glued a smaller piece (5.5×5.5 cm) that fits (nearly) the inner diameter of the glass vase in the center of the larger one. The width of hole for the heater is aligned to the diameter of his glass rod so the little bigger head could keep down the top plate. The tee thermometer is plugged through a 8 mm hole and fixed by a rubber band.

top plate

top plate

The PCB holder is made from a strip of the acrylic glass and two cupping vessels so only one-sided PCBs are possible for now. In a first run I mold the top cover and the PCB holder together by heating the ends and the plate with a gas torch. It holds bombproof till I tried to fix the angle of the holder a little by heating the junction again. After cooling down it breaks of – I think the heat applied to much stress to the material. A little of cyan acrylic glue fixed that mistake. Lesson learned: Don’t mold. Just glue!

PCB holder, thermometer and heater

PCB holder, thermometer and heater

heater - removed limitter

heater – removed limiter













I had to remove the mechanical temperature limiter to get the needed 45..50 degree Celsius for the etchant. I simply used a rasp for this purpose. A first test with 1 liter of water shows that the machine needs ~25 minutes to heat up from 16 to 48 degree.The hysteresis of the mechanical temperature switch is 6 degree so the etchant cools down till 42 degrees – 3 degree below optimum. But cooling down takes that long that I could etch one PCB inside the temperature frame between 48 and 45 degree. For now that fits my needs (I do not plan to go into mass production).

working heater is indicated by yellow ligth

working heater is indicated by yellow light

Finally I filled in the etchant: 200 gram sodium per sulfate and 900 ml water. The finished etching machine looks not so bad:

finished etching machine

finished etching machine

A first run of the complete setup produces great results.  Etching of the complete board takes ~10 minutes. The area of the PCB that was in the stream of the air bubbles was ready after 7 minutes. 3 minutes more for the rest – no under-etching at all.  Some samples below…




And finally the one I’m most happy with (cause it shows that even that small structures are not the limit):



And yes, the numbers are not mirrored. Two bad things about glass vase: due to the  small diameter the size of the PCBs is limited to ~8 cm on one side.  The second is about filling the etchant from the vase into a bottle. It wont work very well. The vase has a cutted border so some of the liquid “hangs” on the glass and flows down of the outside of the vase. But after that great success I ordered a bigger glass vase with a diameter of ~11 cm and a border that is round molten. I think version 0.2 will solve that problems.

collected: compile Qt on Ubuntu 12.04 and other snippets from work…

posted by on 2012.07.18, under general, linux, programming, userland

After some sporadic crashes of a Qt-application (not my fault – gdb says it comes from the QT core…, Ubuntu 12.04/32, QT SDK 4.8.1 binary) I decided to build Qt from the sources… but configure failes with “missing xlib”-errro. solution:

sudo apt-get install libxext-dev

for using the full beauty and power of Qt the following additional devel-deps should be installed:

sudo apt-get install libXrender-dev libicu-dev libfontconfig1-dev libxrandr-dev libxinerama-dev libglib2.0-dev libgtk2.0-dev

… easy. huh?!?
for proper fonts & style run configure with the parameters “-gtkstyle -fontconfig -glib” – or it looks wired…

configure throws some warnings/errors about missing dependencies… that reminds me that self-checking for a given library can be done with

pkg-config --cflags <libname>

it returns the compile-flags (mostly paths) or an error if the lib is not present. by replacing the –cflags with –libs the needed linker flags are dumped.

the following snipped was/is useful for dumping log-data:

cat `ls  -lrt | sort -k6,8 -r | awk 'NR==1{ print $9 }'`

it prints the oldest file in the directory to stdout (ohh… we assume there are only regular files).

why writing this down?!? Qt is still compiling… nothing left to do… should read a book.

collected: SELinux-module example for mod_tile

posted by on 2012.02.05, under collected, configuration, linux, security

For a project@work I had to setup an open street map server on Scientific Linux 6.1 (64 bit) for rendering the map of the BRD. For this I installed all needed components – and run into big trouble with mod_tile. This module is responsible for taking queries for map-tiles from the apache, forward it to the render daemon and deliver the images back. mod_tile and renderd communicate via an unix socket. And SELinux prevents mod_tile – that runs in the context of httpd – to access the socket. A short grep of the web gives a general answer: disable SELinux. Since SELinux was also a long time common problem to me (yes, I used echo “0” > /selinux/enforce some times) I decided to accept the challenge… and after reading a lot I got a solution:=).

The following description should work in general if you have trouble with “access-denied-by-SELinux”-problems. The process is quite easy: use the output of the SELinux-audit-logging for create a probate module. Step by step:

0. be sure that SELinux is your problem. Maybe you got error messages like “permission denied” when accessing files – and you already give full access via chmod/ (if the application gives no output use strace and grep for EACCES, use -e trace=… to filter systemcalls) and/or set the correct security context by chcon/restorecon. Have a look at the boolean shortcuts (getsebool -a | grep ) to check if there is an option to permit the needed action/access.

1. check SELinux-audit-log (/var/log/audit/audit.log) for entries that are related to your problem. If there is nothing enable audit by restart your machine with an additional kernel parameter audit=1. For mod_tile we captured 2 entries:

type=AVC msg=audit(1328183212.312:383): avc:  denied  { connectto } for  pid=2314 comm="httpd" path="/var/run/renderd/renderd.sock" scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket
type=AVC msg=audit(1328182336.427:158): avc:  denied  { write } for  pid=2017 comm="httpd" name="renderd.sock" dev=sda2 ino=2097727 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:var_run_t:s0 tclass=sock_file

Put the relevant entries into a separate file like audit.out. module the long way – so you see what happens…

/*build the module description aka "the source" into apachemodtile.te*/
#>cat audit.out | audit2allow -m apachemodtile > apachemodtile.te
#>cat apachemodtile.te
module apachemodtile 1.0;
require {
type unconfined_t;
type var_run_t;
type httpd_t;
class sock_file write;
class unix_stream_socket connectto;
#============= httpd_t ==============
allow httpd_t unconfined_t:unix_stream_socket connectto;
allow httpd_t var_run_t:sock_file write;

/*build the binary module apachemodtile.mod*/
#>checkmodule -M -m -o apachemodtile.mod apachemodtile.te
/*build a SELinux policy module package in apachemodtile.pp*/
#>semodule_package -o apachemodtile.pp -m apachemodtile.mod

2b. use audit2module – does all of 2a in one step:

#>cat audit.out | audit2allow -M apachemodtile

3. install the module permanently:

/*modul goes (SL61) to /etc/selinux/targeted/modules/active/modules/apachemodtile.pp*/
#>semodule -i apachemodtile.pp

After this mod_tile was able to connect to the socket of the renderd. Quite easy :)

multimeter GVA-18B protocol & dump tool

posted by on 2012.02.04, under electronics, programming

A wile ago I bought an inexpensive multimeter on ebay: G VA 18 B. For ~30€ it comes with autorange measurement for voltage, current, frequency, resistant, capacity and … temperature (with an internal and external sensor). The meter has serial interface based on an infrared diode on the top.The connection to the pc is done with a CP2030-based serial-usb adapter cable (also in the package).

GVA18B, also sold as VA18

GVA18B, also sold as VA18

Unhappily the offered software won’t work for me – it does not see the virtual COM-port (and it only works on Windows). So I decided to write my own. I connected to the meter via putty – and got only binary crap. With the help of some lines C# (I decided to train my C#-“skills” – can’t remember the reason) to dump the output in hex/binary and some sample data I figured out the protocol… great hardware but ugly protocol. It seems our friends in HongKong simply map the data of the display controller to some bytes… The facts:

Every sample is decoded into 14 bytes. The high-nibble of each byte contains the position within the stream (bits 4,5,6,7; P={16,32,48,64,..,224} or shifted by 4 bits P={1,..14}). The bytes 1, 10, 11, 12, 13, 14 containing control informations about the selected unit, the range and further functions. The table below shows witch bit in each byte is set for a specific function (high nibble set to zero, first number is decimal value, in brackets the relevant bits):

Each numeric position on the display is encoded into a pair of bytes [1,2], …, [7,8]. The association is given in the following graphic. Bytes 1,3,5,7 represent position “a”, 2,4,6,8 position “b”:

The meaning of Bit 3 in byte “a” depends on the position of the digit. For the leftmost digit it indicates a leading minus. For the other positions it indicates that the digit is the first part of the fraction.

In the attached code you find a class that handles all the encoding stuff – GVA18BProtocolDecoder. You can drop the received data into it – it does the rest. For simple use it offers an interface for registering a handler that is called when new data arrives. The data can then be fetched by using some convenience methods. The dump2display does what is names – it simply puts the data on the screen (and shows how to use the decoder). And yes, the code is over sized and not very sexy – yet. But it is under the GPL3 – use it as you can: GVA18BDataDump

collected: unbrick dockstar with buspirate

posted by on 2011.11.26, under collected

By killing the nand off his dockstar a colleague gives me the final trigger to buy a BusPirate – an awesome tool for dealing with several buses and protocols – including JTAG. I found tree great HowTo’s on debricking the dockstar here, here and here.

Unfortunately there are some stumbling blocks on the way to a recovered dockstar…

1. dockstar uses 3.3V-level for the serial communication – so a ftdi232-based serial-ubs-adapter could do the job. But my colleague decides to use some china crap (see image below) with an PL2303 – normally no problem. But two weeks ago I updated my M$-PC to Windows7/64. The driver offered by Prolific (version won’t work anymore for this “brand new OS”. Someone mentioned a a GPS-device that is based on/contains the PL2303. The driver for that GPS contains the driver for the PL2303 with version = and… it works for Win7/64.

PL2303-based adapter made in china (with a build-in short circuit)

2. BusPirate is advertised with the attribute “also a JTAG-device by using in conjunction with OpenOCD”. But this depends on the version of the firmware of the BusPirate. My unit was delivered with FW 5.10 – won’t work with OpenOCD (I did a fresh build with the GIT-sources and a manual fetched 0.5.0 – booth won’t work). I’d go down step-by-step in FW version till FW5.8 (okay, 2 steps != a long way) and now it works. Sadly I had to disconnect/connect the BusPirate before I could start a new OpenOCD session every time.

below the procedure that works for me…
in the openocd-shell:

> init
> halt [[[press reset&hold@dockstar, press return]]]
Halt timed out, wake up GDB.
[[[release reset@dockstar]]]
target state: halted
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x000000d3 pc: 0xffff0000
MMU: disabled, D-Cache: disabled, I-Cache: disabled
> dockstar_init
> load_image uboot.kwb 0x800000
524288 bytes written at address 0x00800000
downloaded 524288 bytes in 100.608101s (5.089 KiB/s)
> resume 0x800200              

now move (fast) to the serial terminal, press <any> key…

U-Boot 2010.09 (Oct 23 2010 - 11:49:22)
Marvell-Dockstar/Pogoplug by Jeff Doozan

SoC:   Kirkwood 88F6281_A0
DRAM:  128 MiB
NAND:  256 MiB
*** Warning - bad CRC or NAND, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   egiga0
88E1116 Initialized on egiga0
Hit any key to stop autoboot:  0
Marvell>> nand erase

NAND erase: device 0 whole chip
Skipping bad block at  0x06ba0000
Erasing at 0xffe0000 -- 100% complete.
Marvell>> nand write.e 0x800000 0x0 0x80000

NAND write: device 0 offset 0x0, size 0x80000
 524288 bytes written: OK

remarks: nand erase cleans the complete nand (ffe0000 = 256 MiB),
the write.e is used for skipping bad blocks of the nand. since there is no dockstar-system in the nand the dockstar reboots and reboots and reboots…

Result: DockStar is back to live, and I got a BusPirate.

collected: svn relocate & add all subdirs but not…

posted by on 2011.11.14, under general, programming

After some changes in our infrastructure@work svn failed to find the server… (svn info shows you the url). huh, seen&solved years ago… and now here so I can’t miss the information in the future.

~>svn switch --relocate <old_addr> <new_addr>

I also found a piece of old script I wrote years ago for adding subdirs in svn but not a given set of name directorys and file-extensions:


# script add all but not
# add all files not versioned in and below the current dir to the svn
# exeptions: ignore_dir and ignore_file_suffix (seperated by |)

#ignore directory paths with names...
#ignore files with names...

list=`svn status | grep ? | awk {'print $2'}`

for l in $list

  to_add=`echo "$l \<($ignore_dir)\> \<($ignore_file_suffix)\>$" \
      | awk '{
        where = match($1, $2)
          if (!where) {
            where = match($1, $3)
              if (!where)
                print 1
                print 0
          } else
            print 0   

  if [ $to_add -gt 0 ] ; then 
    echo "+++ADDITION+++"$l
    svn add $l
    echo "---IGNORE---"$l


By commenting out the “svn add$I” you can do a “try run”.


posted by on 2011.10.31, under programming

I searched for a tool for managing project tasks for me and my colleagues – and I found – a great service offered by the 6 Wunderkinder GmbH. It’s a free task list manager that runs in a browser or – as a rich client – on nearly every (common) platform.

But I missed something like a dedicated page that shows only one auto-updated task list so I can display it on a big screen in our office.

But hey – this is the world of web-services – everyone can access any data in any needed way. Due to the SOP there is no way to call the AJAX-service directly from my page – but with a little help of a JSON-P-alike php-script for reading the data the “magic” is done. Hint: the script returns all lists with active entries. A simple html/javascript-page is used for displaying the (selected) data. You can test it under

The needed files can be downloaded here.

(Don’t forget to set your email/pwd in getTaskList.php and the name of the list in the view-page index.html)

Edit: update the view-page to look a little…
Edit2: update the view-page – now has a css-progressbar/shows time&date…

collected: change data dir of mysql results in errorcode 13

posted by on 2011.10.13, under general

by setting up a mysql-db (on Scientific Linux 6.1 I run into trouble cause I’ve changed the data-dir to somewhat outside of /var/lib/mysql… and it won’t work, got errorcode 13 – permission denied. chowned, start – failed. checked permissions twice… but the net has the solution (spreaded over some pages) on some “modern” linux systems SElinux secures anything. more or less usefull. simply setup the tables and change the SElinux security context of the new data dir to that of the former data dir. and (if needed/configured) don’t forget to create the inno-db-dir manually… sample for data-dir is /data/db/mysql with innoDB at /data/db/mysql/innodb:

#>mkdir -p /data/db/mysql/innodb
#>chown -R mysql.mysql /data/db/mysql
#>mysql_install_db --user=mysql --ldata=/data/db/mysql
#>chcon -R --reference=/var/lib/mysql /data/db/mysql
#>/etc/init.d/mysqld start

Addition: same fun for apache:

#>chcon -R -t httpd_user_content_t /data/www/html/

collected: get linux version and flavor

posted by on 2011.10.11, under general

I need this seldom – and then I can’t (completely) remember…
so I wrote it down here. The first thing that comes every time back to brain is take a look in /etc/issue:

>cat /etc/issue
Ubuntu 10.04.2 LTS

Not so much information. Not reliable. The second is lsb_release:

>lsb_release -a
No LSB modules are available.
Distributor ID:  Ubuntu
Description:  Ubuntu 10.04.2 LTS
Release:  10.04
Codename:  lucid

Thats it.

collected: TI Chronos display addressing

posted by on 2011.04.12, under collected, programming, TI Chronos

Update: Got time to play again with the Chronos and … huuu, fu**. There was a big mistake in the old version – all bits must be  (old+1)%8… its corrected now.

This is a “cheat sheet” that contains the assignment of the LCD_B memory (0x0a20 to 0x0a2b) and its bits to the wristwatch’s display elements.

src: base image taken from SLAU292C (p.77, LCD segment map)

as .pdf
as zipped svg