Monday, 5 September 2011

Bristlebot fun

The magnet wire has double role a construction and stabilization device.
One day I saw a video of a nice toy called bristlebot. Basically it was a small vibration motor mounted on a top of a toothbrush with a battery and which moved on a flat surface. It seemed so fun that I got a motor and built one myself. The battery holder served before as a cap of a HDMI cable, toothbrush had seen the best of its days and the wires were easy to find too. Two 1,5V batteries in series provide more than enough of juice, as the motor started even at 0,3V. The cap just keeps two batteries better than one, and one toy can never have too much power, I've been told. The device runs quite nicely, especially after tuning the brushes. The eyes are actually at wrong end, as it seems to move better to other direction, but what good is a bug without eyes;)

Tuesday, 23 August 2011

I learned a new way of wiring; way of the wiring pen

Making circuits with perforated board is simple, but it may also be really slow. All my connections so far were done with PCB insulated and uninsulated tinned wires. I got quite fed up with that process and searched for faster ways of working. Dear Google gave some better ways to carry current from place A to B. Please look this excellent tutorial by R.Clarke, one article at Instructables and the thing draw into extreme, really into a art by sir Elm Chan.
After web learning session I had purchased some 0.25mm and 0.1mm enamelled wires. The thicker of wires seemed to have too good insulation for its spec sheet (220C melting point, my ass), as I was unable to solder it even with burning, too hot 450C iron. The thinner wire instead could be soldered by a measly 430C and 3-10 seconds of time. After some sweat, trial, retries and burned fingers I found a suitable work flow;
  1. Press the other end of wire by finger against the pcb
  2. Use the wiring pen (or a just tip of a mechanical pencil, where the thin and soft wire is easy to insert) to make 5-10, tight turns around the leg of component. The turns need to be tight enough, so the wire will not get loose before soldering
  3. Draw wire to the destination. It is easier to work, if there are some extra length in wire, so one can lift and move them even after soldering.
  4. Again, press the wire with a finger against pcb while making 5-10 rounds around the destination component leg.
  5. It is ok to leave +1cm of wire before cutting it by pliers. If one tries to cut it too close the wire, the wire may get loose and re-inserting it with tweezers takes quite some time. If the wire gets loose, it may be easier and faster to just replace it with a new one. Of course, if there are multiple, unsoldered wires on multiple layers, the replacement may be tricky too.
  6. Goto 1 until some amount of wires are drawn. At the beginning, it may be easier to draw and solder wire by wire, but after some experience they can be done in batches.
  7. It is solder time. Adjust the iron to the proper wire insulation melting point. On my wire and soldering station the best temperature is 430C. The melting insulation is said to produce toxic (!!!) fumes, so some kind of extra fan is good to have.
  8. Put the tip of iron against the wire and component leg, insert solder to improve heat transmission and let the insulation burn. It is funny to see, that while the insulation vaporises, the solder blob bubbles and eventually it just sucks itself into the solder pad. After some trial and error one learns the technique.
  9. The melting insulation seems to be quite hostile against the solder iron tip, so one needs to clean the tip in sponge after each joint or few. The tip may also require re-tinning quite often too.
  10. After soldering, cut off the excess wires by a sharp knife, I used a simple Stanley blade knife. The connections need to be tested, as the hot solder or flux (?) may make some unwanted connections to fellow neighbour pads.
After learning to use, the enamelled wire is extremely handy while working with the perforated board. One does not need to peel the insulation off, no need to measure the wire length before wiring or cutting and due to it being insulated, they can be drawn on top of each other. All this means that it takes a fraction of time to make a prototype than before, when using a typical un-stranded PCB insulated wire. Of course, there are drawbacks; the wire I used is a bit thin, one may need a magnifying glass to verify or trace the contacts. The energy carrying capacity is also low, so it is better to use it only for logic level connections, not for grounding or power supply lines. Also on higher frequencies this layout may not be a option, but who needs over few megahertz anyway?-)

One wired and soldered board. Note the thin as hair wires, ignore the fixes and awful blobs;)

Example of the work in progress, some wires drawn but not yet soldered.
The reel of wire and its holder, also the "tool" used as a ad-hoc substitute of a wiring pen.

Experiments with PS2 controller, HD44780 and nRF24L01+

Once in a while my robot project gets into surface. This time I decided to get back into bottom(s) up design, and build a remote to it. I took the parts which were already in my drawers;
  • Atmel Atmega8 for CPU
  • HD44780-compatible LCD, 8x2 chars of GUI
  • PlayStation 2's Dualshock controller as input device
  • Connector from PS2 extension cable for interfacing the controller and board
  • nRF24L01+ module to transfer the command and conquer data wirelessly
The idea in nutshell is to be able to read the PS2 controller by Atmega8, display the control data by LCD and transfer it to the mr Robot by nRF24L01+. After drawing the draft of schematics, I tried a new wiring technique for me; making connections with a thin enamelled copper wire by a pencil, and soldering it directly through the insulation. More of that on next post.
I rewrote my HD44780 driver code using a original Hitachi data sheet and after debugging and rewiring the mixed D6 and D7 lines it had a visible output. The PSX controller code was also a nice learning experience in firmware and hardware debugging, but it finally worked very well. Luckily the protocol and interface are well documented, so I could blame for troubles only myself. Perhaps next time I will first double check the port assignments, as it is much better to use PINC port for reading pins in port C, instead of PIND, which was used in my original code:-)
The nRF24L01+ driver part is still in progress and actually completely untested, which can be witnessed from the board too, as there is no <3.3V power supply even wired for it. The power source needs some re-evaluation as a whole. I planned to use a 9V battery and a simple pair of L7805 and 78L33 for 5 and 3.3V rails. But this might also be a nice test bench for BL8530 step up converters I have waiting for a inspirational SMD SOT-89 soldering session. Well, currently the whole system is powered by the USBASP-compatible programmer.

Underside, logic level connections done mostly by the 0.1mm enamelled copper wire. The connections may look a bit scary, but they work.

Sunday, 21 August 2011

LED matrix clock

Clock in action.
For some time I have been planning on making a digital clock. The main reason for building one is of course just a hobby; building one nowadays just does not pay back money wise. What I wanted was a fully programmable LED matrix, not just dull 7 segment modules. After some eBay searching, I found cheap 8x8 modules and ordered them. After that was the time for final design.
One interesting dilemma was that how to light 128 LEDs with a CPU, that has only 16 GPIO pins. The problem is somewhat reduced by the matrix modules themselves, which provide only 16 pins: 8 anode and 8 cathodes. The modules can even share the cathode pins, so one only needs 16+8 pins, which may be driven by couple of 74595 shift registers and 8 AVR IO pins. The '595 drive the LED anodes and the AVR IO port sinks the cathodes via current limiting resistor.
In this design, the '595 are driven perhaps too close to their limits, but in practice they work fine for this first version. I did order some real LED driver chips (MAX7219) for some other project, perhaps I'll try to use them in the next revision of the clock.
The mechanical building was a bit harder than I thought, as the LED matrixes had a slightly incompatible spacing as the normal perforated 0.1" board I use and the sheer amount of pins (2*16+24=56) which each needed a short wire on the daughter board.
After the CPU board was ready, it was time to do the easy part, i.e. the software. The code is structured as a state machine, which is ran from a timer interrupt 12500 times a second. On each step the code shuts down one, and lights one led, from left to right. After one row is shown, the next anode line is grounded and others set to high-z state. The rest of the time the CPU sleeps in the idle mode to save some power.
The time keeping itself is the easiest part, as it is handled mostly by a DS1302 chip. The chips is easy to use via three wire serial interface, and it even has its own circuit to handle the backup power source. For backup, I chose a super capacitor, but have not yet actually written code for charging it. The cap is rated for 5.5V, which should drive the clock chip for quite a many days, but perhaps I'll try to play safe and make the DS1302 to drive only 3.3...4 volts into it.
Anyway, the clock works now and is waiting for a enclosure and place to keep it.

Here are the basic components:
  • CPU: Atmel Attiny26L-8PU (Obsolete part, but nice to use as the port pins are close to eahc other)
  • RTC: DS1302
  • Output: 2*LED matrix (8x8)
  • IO multiplexing: 2*74HC595
  • 1.0F (!!) super capacitor
  • resistors, capacitors and switches, 32768Hz crystal

Schematics drawn with Eagle. The pin headers SV1, SV2 and SV3 connect to the daughter board and ISP to the programmer. R9-10 are there to protect CPU from ESD, just in case.
Undersides of both boards.

Top side, which shows also the huge capacitor. The cap seemed slightly smaller on the ad, so it did not fit well into board;)

Saturday, 19 March 2011

SSD update for Asus EeePC 901

For a while I have struggled with the small but slow SSD's in the trusty old EeePC 901. The machine was born in 2009 with 4GB of "fast" and 16GB of very slow SSD disks. The 4GB was used for Ubuntu Netbook edition and 16GB one for the /home and apt's temporary -directories.
A some time ago I bought a cheap ($93 with p&p on eBay), new and shiny KingSpec KSD-SMP.1-032MJ, a 32GB Mini-Pcie SATA SSD. Installation was really easy; two screws off, lid open, two more screws out, replace SSD and reverse.
New drive, well packaged to survive posting across the globe. Check out the funny sticker about warranty;)
Old Phison 16GB drive before its retirement. Under the grey plastic cap resides previous modification, a 2GB RAM upgrade.
New 32GB drive. It could also be modified to fit into the shorter, 50mm card slot. Besides making irreversible cut to PCB, that would also have required opening the EeePC 901 completely. Perhaps some day, if the current disk fills up I will add both the 32 and 16GB disks at once.

Most troublesome was installation of new Ubuntu Natty, which is still in alpha-3 stage. The installer froze always, likely due to finding the "unknown" formatted partitions from 4GB disk, which are required for Asus' Speedbooster, which speeds up the BIOS' boot sequence. Fortunately the well known bug was fixed after few days, so I could proceed with the installation. After restoring the home directory from backups, I had a whole system in a single 32 GB disk. No more trouble with insufficient disk space on system upgrades:-)
After all, the system seems to start now considerably faster, there are less waits on disk when surfing the web, etc.
Some simple, non scientific sequential IO benchmarks on top of ext4 file system for the old and new disks:

dmesg:[    1.537966] scsi 1:0:1:0: Direct-Access     ATA      ASUS-PHISON SSD  TST2 PQ: 0 ANSI: 5
[    1.538571] sd 1:0:1:0: Attached scsi generic sg1 type 0
[    1.539758] sd 1:0:1:0: [sdb] 31522176 512-byte logical blocks: (16.1 GB/15.0 GiB)
[    1.540517] sd 1:0:1:0: [sdb] Write Protect is off
[    1.540529]  sda: sda1 < sda5 > sda3 sda4
[    1.540549] sd 1:0:1:0: [sdb] Mode Sense: 00 3a 00 00
[    1.540803] sd 1:0:1:0: [sdb] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA

write:
tero@wendy:/mnt/data/home/tero$ dd if=/dev/zero of=test.zero bs=512 count=5M
5242880+0 records in
5242880+0 records out
2684354560 bytes (2.7 GB) copied, 254.203 s, 10.6 MB/s
tero@wendy:/mnt/data/home/tero$ dd if=/dev/zero of=test.zero bs=4096 count=400K
409600+0 records in
409600+0 records out
1677721600 bytes (1.7 GB) copied, 169.388 s, 9.9 MB/s
tero@wendy:/mnt/data/home/tero$ dd if=/dev/zero of=test.zero bs=16KB count=100K
102400+0 records in
102400+0 records out
1638400000 bytes (1.6 GB) copied, 156.973 s, 10.4 MB/s
tero@wendy:/mnt/data/home/tero$ dd if=/dev/zero of=test.zero bs=64KB count=50K
51200+0 records in
51200+0 records out
3276800000 bytes (3.3 GB) copied, 325.498 s, 10.1 MB/s
tero@wendy:/mnt/data/home/tero$ dd if=/dev/zero of=test.zero bs=1MB count=5000
5000+0 records in
5000+0 records out
5000000000 bytes (5.0 GB) copied, 607.437 s, 8.2 MB/s

read:
tero@wendy:/mnt/data/home/tero$ dd if=test.zero of=/dev/zero bs=512
11160136+0 records in
11160136+0 records out
5713989632 bytes (5.7 GB) copied, 155.788 s, 36.7 MB/s
tero@wendy:/mnt/data/home/tero$ dd if=test.zero of=/dev/zero bs=4096
1395017+0 records in
1395017+0 records out
5713989632 bytes (5.7 GB) copied, 155.857 s, 36.7 MB/s
tero@wendy:/mnt/data/home/tero$ dd if=test.zero of=/dev/zero bs=16K
348754+1 records in
348754+1 records out
5713989632 bytes (5.7 GB) copied, 157.91 s, 36.2 MB/s
tero@wendy:/mnt/data/home/tero$ dd if=test.zero of=/dev/zero bs=64KB
89281+1 records in
89281+1 records out
5713989632 bytes (5.7 GB) copied, 156.168 s, 36.6 MB/s
tero@wendy:/mnt/data/home/tero$ dd if=test.zero of=/dev/zero bs=1MB
5713+1 records in
5713+1 records out
5713989632 bytes (5.7 GB) copied, 156.46 s, 36.5 MB/s




some background for /dev/zero's throughput, which should not affect figures too much

tero@wendy:/mnt/data/home/tero$ dd if=/dev/zero of=/dev/zero bs=512 count=10M
10485760+0 records in
10485760+0 records out
5368709120 bytes (5.4 GB) copied, 19.0382 s, 282 MB/s
tero@wendy:/mnt/data/home/tero$ dd if=/dev/zero of=/dev/zero bs=1M count=10000
10000+0 records in
10000+0 records out
10485760000 bytes (10 GB) copied, 7.32884 s, 1.4 GB/s


And the new disk:
dmesg:
[    1.072397] ata1.01: ATA-7: KingSpec KSD-SMP.1-032MJ, 100415, max UDMA/133
[    1.072414] ata1.01: 62947328 sectors, multi 1: LBA48
[    1.080431] ata1.01: configured for UDMA/133
[    1.080802] scsi 0:0:1:0: Direct-Access     ATA      KingSpec KSD-SMP 1004 PQ: 0 ANSI: 5
[    1.081177] sd 0:0:1:0: [sda] 62947328 512-byte logical blocks: (32.2 GB/30.0 GiB)
[    1.081303] sd 0:0:1:0: Attached scsi generic sg0 type 0
[    1.081424] sd 0:0:1:0: [sda] Write Protect is off
[    1.081435] sd 0:0:1:0: [sda] Mode Sense: 00 3a 00 00
[    1.081543] sd 0:0:1:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA

tero@wendy:~$ uname -a
Linux wendy 2.6.38-7-generic #36-Ubuntu SMP Fri Mar 18 22:05:25 UTC 2011 i686 i686 i386 GNU/Linux

tero@wendy:~$ mount
/dev/sda1 on / type ext4 (rw,noatime,errors=remount-ro,commit=0)

tero@wendy:~$ dd if=/dev/zero of=test.zero bs=512 count=5M
5242880+0 records in
5242880+0 records out
2684354560 bytes (2.7 GB) copied, 92.2996 s, 29.1 MB/s
tero@wendy:~$ dd if=/dev/zero of=test.zero bs=4096 count=500K
512000+0 records in
512000+0 records out
2097152000 bytes (2.1 GB) copied, 40.5247 s, 51.7 MB/s
tero@wendy:~$ dd if=/dev/zero of=test.zero bs=16KB count=100K
102400+0 records in
102400+0 records out
1638400000 bytes (1.6 GB) copied, 31.5863 s, 51.9 MB/s
tero@wendy:~$ dd if=/dev/zero of=test.zero bs=1MB count=3000
3000+0 records in
3000+0 records out
3000000000 bytes (3.0 GB) copied, 67.5938 s, 44.4 MB/s

tero@wendy:~$ dd if=test.zero of=/dev/zero bs=512
5859375+0 records in
5859375+0 records out
3000000000 bytes (3.0 GB) copied, 36.39 s, 82.4 MB/s
tero@wendy:~$ dd if=test.zero of=/dev/zero bs=1024
2929687+1 records in
2929687+1 records out
3000000000 bytes (3.0 GB) copied, 35.6681 s, 84.1 MB/s
tero@wendy:~$ dd if=test.zero of=/dev/zero bs=4096
732421+1 records in
732421+1 records out
3000000000 bytes (3.0 GB) copied, 35.9203 s, 83.5 MB/s
tero@wendy:~$ dd if=test.zero of=/dev/zero bs=16KB
187500+0 records in
187500+0 records out
3000000000 bytes (3.0 GB) copied, 36.1911 s, 82.9 MB/s
tero@wendy:~$ dd if=test.zero of=/dev/zero bs=64KB
46875+0 records in
46875+0 records out
3000000000 bytes (3.0 GB) copied, 36.289 s, 82.7 MB/s
tero@wendy:~$ dd if=test.zero of=/dev/zero bs=1MB
3000+0 records in
3000+0 records out
3000000000 bytes (3.0 GB) copied, 36.417 s, 82.4 MB/s

tero@wendy:~$ dd if=/dev/zero of=/dev/zero bs=512 count=10M
10485760+0 records in
10485760+0 records out
5368709120 bytes (5.4 GB) copied, 23.139 s, 232 MB/s
tero@wendy:~$ dd if=/dev/zero of=/dev/zero bs=1MB count=10000
10000+0 records in
10000+0 records out
10000000000 bytes (10 GB) copied, 6.95549 s, 1.4 GB/s