Friday, 23 November 2012

Large format vinyl cutter at BuildBrighton Foison C24

Last night was BuildBrighton night (in fact, almost every night is a BuildBrighton night these days, but Thursdays are the "traditional" come-along-and-hang-out night) and as is usual, come the witching hour, cool things start to happen.

This video was taken at around ten past midnight, after we spent a couple of hours restoring the large format vinyl cutter that we donated a few months back. It's a Foison C24 and has been used about three times in it's lifetime. Hopefully, now it's in it's new home and working, and more people have access to it, it'll get used quite a bit more.

As you can see, it's quite a whizzy-fast machine. Because it's designed to use a drag knife, it takes corners quite slowly, but really flying down the straights!




For testing, we replaced the drag knife with a fat-tipped Sharpie and drew on some copper board. Of course, it's only a matter of time before we're drawing PCBs directly onto the copper board, by-passing the whole press-n-peel stage of etching ;-)

Wednesday, 21 November 2012

DipTrace for home etching, gerber export, 3d views and milling outlines

The more time we spend with DipTrace, the more we like it, here at Nerd Towers.
We first came across it while designing PCBs for our miniature guitars last year - changing over from ExpressPCB because we needed to generate gerber files to have some circuit boards manufactured online.

It's easy to use, has a massive library of components, but uses an approach similar to Eagle; when placing components in the schematic, you have to choose the "correct" component with the appropriate footprint while you're drawing the schematic. We much prefer the ExpressPCB method: draw a schematic then link it to the PCB designer - so long as the number of pads in the PCB layout software matches the number of pins in the schematic, you can use pretty much any component footprint to represent any component in the schematic.

As a result, we still turn to ExpressPCB whenever we need to "knock out" a few boards for home etching.
But since we've had to design some more boards for manufacture (for a recent alarm clocks project) we've returned back to DipTrace to generate more gerbers.

And we've found that DipTrace has some pretty cool features - even for the homebrew enthusiast. Firstly, you can create homebrew boards easily and - using the ExpressPCB method - print to a PDF file using CutePDF and flip in Inkscape, reading for printing onto some press-n-peel.



Of course, DipTrace can export to Gerber (so the file(s) can be emailed for manufacture by a professional PCB fabricators). But it also has a few other handy export options.

We've already discovered the brilliant 3D view:


The great thing about this 3d generator is that you can place components so that they "hang off" the board. Not many tools let you do this. In the example above, we've created our audio board but cut the dimensions down, so that the SD card holder is fixed at one end. There's no need to waste copper board under the rest of the sd card holder - not all PCB layout tools allow you to create a board outline smaller than the components on it!

As well as 3D, and creating toner-tranfer images, DipTrace supports exporting to DXF.
Why is this so impressive? Well, if you've a CNC router, you can get it to draw around the outside of each of your pads and traces:


Wow! Now that's cool. Anyone with any experience of using Mach3 or similar CNC software knows that it's relatively easy to get from a DXF drawing to some g-code which we can use to drive the CNC router and - rather than all that nasty etching with stinky chemicals - we could rout out the PCB board from a sheet of copper-clad board.

All these output options from the same PCB layout. DipTrace is looking like a really useful bit of kit. And perhaps something we should persevere with for a little while. After all, up to 500 pins, it's FREE as well.

Tuesday, 20 November 2012

Etching heater

Etching with Ferric Chloride is a messy business. So the quicker you can get it over with the better - and for a few reasons. One way to decrease the time taken to etch is agitation: basically stir the mixture or dunk the board in and out of the etchant.

The problem with this, of course, is more opportunity for spillage. And with ferric chloride being such a nasty staining solution, you don't want it splashing around the place.

Another way to speed up etching is using heat. Ferric Chloride works best at about 50 degrees. But sitting the solution in a bath of hot water only increases it's temperature by a few degrees at best. So we tried one of these things - it's called an etching heater, but really it's just a fancy aquarium heater!


It's like a super-duper tropical aquarium heater in a sealed glass case- complete with temperature control on the top, so you can set the thermostat to anywhere between 40 and 60 degrees: perfect for ferric chloride etching! Just search ebay for "etching heater". This one cost less than £15 including delivery to the UK and took about 8 days to arrive.

We put about a litre of ferric chloride solution (made up quite strong, with a full 500g packet of crystal dissolved into about 1L of warm water) into a sweetie jar. This should allow us to etch rather larger boards if we need to. Just stand the heater in the solution, switch on and back away. After about five minutes, the entire thing is up to perfect etching temperature.

(heating the solution is easy - plop in the heater and switch on!)

A relatively small board can now be etched in about two-to-three minutes, rather than the 15-20 minutes it has been taking recently, when etching "cold" (as the winter nights draw in, it does get colder in the nerd cupboard, so ambient temperature is about 16-20 degrees).


The great thing about etching quickly is that because the board is in the solution for a lot less time, the chance of under-cutting is much less (under-cutting is where the etchant eats away at the copper under the toner-transfer mask because the board is left for too long in the solution). By etching hot and quickly, we get really sharp, clear etching, even with thin traces. 


In the photo above, we've managed to get traces down to 0.2mm and they've etched perfectly. When etching "cold" we would rarely go below 0.38mm trace size to avoid over-etching the tiny thin traces.


Here's the board cleaned up, with a micro sd card connector soldered in place, ready for populating. In short, 

Friday, 16 November 2012

DipTrace and the amazing 3D render

I recently had to get some PCBs made up for a little project, so had to leave my favoured ExpressPCB behind and use DipTrace again, in order to generate some gerber files for manufacturing (normally we'd just etch our own boards, but time is tight with this one, so they're on a three-day turnaround from a UK-based manufacturer).

I was looking for a gerber viewer when I came across Jason's post about a web-based 3d renderer: https://plus.google.com/u/0/105009608886388132613/posts/1oST39owVAZ

Now that looked exciting. I uploaded the gerber files generated from DipTrace and eagerly waiting for the image to appear..... nothing. Whether it was the gerber file, my lack of 3d graphics hardware in my little notebook or something else, I don't know. I do know that other people commented that they couldn't get it to work either. So no 3D renderings for us.....

Then I spotted this little icon on the toolbar:


So what would that do....?


Ta-da! A perfectly rendered (and populated) PCB. I'm not quite sure how to get the components to sit down in the board properly (seriously, who solders their components so they stand up like that?) but as a quick overview of how your final board could look (especially now we're moving away from through-hole and trying to use SMT wherever we can) it gives great results!

We might just give DIPTrace another go.
Familiarity and laziness have kept us using ExpressPCB. But these 3D renderings do add a fresh dimension to documenting projects (-no- pun intended) so maybe it's time to give it a whirl. The freeware version is quite restrictive with only 300 pins allowed. But for simple, little projects like this one, that's more than enough!

Thursday, 15 November 2012

DC blocking capacitor

We've had a few questions about the in-line capacitor on our audio player board. This is the capacitor between the PIC pwm output pin and the gate pin on the transistor amplifier. At first glance, it seems a bit counter-intuitive: we're "blocking" the output from the PIC to the speaker. What's it there for?

Well, here's the thing - the circuit will actually work without the capacitor in place.
Go ahead, try it. You can connect the output from the PIC directly to the gate on the transistor, and you'll still hear sound. It might not be quite as loud, but it'll still be an amplified signal. So what does the "blocking capacitor" do?

Consider what's happening - we're using PWM to drive a speaker.
It's not the most efficient use of the speaker, since we're not generating negative voltages, so we're only every driving the speaker "forwards" using a positive voltage. But let's ignore that for a moment!

Our PWM is creating an "average" voltage over a particular time period, to move the speaker by a certain amount. Now most digitally recreated sound waves go from minus the maximum amplitude (let's call it -5V for simplicity) and plus maximum amplitude (e.g. +5V). When there's no sound/signal, there's no voltage 0V.


But because we don't have negative values in our PWM , we're having to use a value 0-255 to represent the full range from -5 (in this example) to +5.

So -5 (the lowest possible value in the wav file) becomes PWM value zero (the lowest possible value in our PWM output). And +5 (the maximum value in the wav file) becomes PWM value 255 (the highest possible value in our PWM output).

So where the audio file is normally zero (half-way between max and min) our output PWM value is actually 128 (half-way between 0-255). When there is no audio signal, our PWM output is 128, or half-duty cycle, or (on average) 2.5V output.



Now driving 2.5v continuously through the coil in our speaker is going to cause it to heat up and over time, eventually burn out the speaker. So what we do is put a capacitor between the output pin and the gate (which in turn controls the amount of current going into the speaker).

So now, while our audio is silent, there's nothing actually coming out of the other side of the capacitor.

  • When the wav signal falls, the capacitor discharges  and creates a high output.
  • When the wav signal rises, the capacitor starts charging up and the "output" side falls low.
  • The output from the capacitor lags the input by a single sample width.

This means that while the signal is fluctuating - ie. we're using an AC signal - the capacitor allows the signal to "pass-through" albeit one sample width behind the input. When the AC signal becomes DC (a period of sustained silence, for example) the output from the capacitor drops to zero and no voltage is passed into the speaker. The "blocking capacitor" acts like a filter - stopping DC current but allowing AC signals through.

This is a very crude method of driving the speaker, but one that works.
The downside is that where a very quiet audio signal is being played, with large gaps of silence, or very quiet background noise, the speaker is hardly active at all, and you can hear all the other "noise" in the line (the PWM carrier signal, for example).

We can hear this at the start of the song being played in the earlier video.
For the first ten seconds or so, the background sound of rain just sounds like a digital noise and you can hear the hum of the PWM signal. This is because parts of the audio signal are being treated as "rippling DC current" rather than a true AC signal. However, once the audio signal amplitude increases, a large AC signal is generated and the blocking capacitor allows all of the signal to pass into the speaker and the audio clarity improves.

Wednesday, 14 November 2012

Different speakers sound different

It's almost so obvious as be incredible!
Here's our PIC-based wav audio player with a cheap 15p speaker from Farnell. The difference between this and the speaker on the alarm clock is amazing! We've tried all kinds of different ways of amplifying the output but the best/loudest to date is this 16 ohm, 700hz, 90dB piezeo speaker with a humble BS170 FET transistor.


The audio in this example is much clearer than with the earlier speaker (and louder too).
Perhaps this is because rather than put the speaker in a box, we're holding it to create a cavity behind the speaker cone. You can definitely hear the speaker gain more definition between hanging loosely and being "encased in flesh"!

Interestingly, the best sound came when we created a tube effect rather than a closed box shape with the hand holding the speaker. Whether this only applies to hands, or to enclosures in general, we've yet to see.....

Wednesday, 7 November 2012

FAT/FAT16 tables - finding the data

Having successfully found the root directory on our sd card, we now need to start actually reading the data back from it. This is the last little link in a chain of
The easiest way to find a file is to load a filename into an 11-byte buffer. The easiest format to use is the name, padded with spaces plus the extension, minus the full-stop; so wav001.raw becomes wav001[space][space]raw. Or, perhaps more accurately, WAV001[space][space]RAW (since FAT16 likes to store filenames in uppercase).

A root directory entry looks like this:


  • The first eight bytes are the file name - FAT16/MSDOS only supported up to eight characters in a filename.
  • The next three bytes are the file extension
  • Then there's an attributes byte
  • Followed by time stamps for the file creation/modified date.
  • The next two bytes are the starting cluster for the data (note, cluster not sector)
  • The last four bytes are the total file length (in bytes)
  • Every root directory entry uses exactly 32 bytes
It's the first bunch of bytes we're interested in - the file name, starting cluster and total file length:
Now we just read the root directory, comparing the first 11 bytes of each 32-byte entry in the root directory to the bytes in our filename buffer and if they match, we've found the file we're interested in.

Once we've got our file, we need to work out the file-length (in bytes) and the starting sector for the first cluster of data.

Byte 26 of 32 is the least-significant byte of a two-byte word  (e.g. 0x02)
Byte 27 of 32 is the most-significant byte of a two-byte word (e.g. 0x00)
The starting cluster for the file in this example is therefore 0x0002

Bytes 28-31 represent the file length, starting with the least significant byte of a 4-byte value.
In this example:
Byte 28 = 0x43
Byte 29 = 0x5e
Byte 30 = 0x09
Byte 31 = 0x00

The total file length is 0x00095e43 which in decimal works out as 613,955
Looking at the file wav003.raw in Windows Explorer confirms that the file is, indeed, 613,955 bytes in size



Now previously, we worked out a whole heap of important things from our MBR (master boot record) including where the actual data started, and the number of sectors per cluster (in a FAT16 formatted disk, this is usually 32 sectors per cluster, making each cluster 16kb)

If we know which sector the actual data begins from, and which cluster to begin reading from, we can calculate at which sector the cluster begins.


unsigned long clusterToSector(unsigned long cluster){
     // a cluster is a complicated thing:
     // first there's an ofset to the master boot record
     // then some reserved sectors
     // then a fat table (maybe two)
     // then the root directory (fixed length)
     // THEN there's the first data block,
     // which is where we start reading our clusters from
     // BUT there's a catch - clusters start from zero not 2
     // so whichever cluster number we've been given, subtract 2
     
     unsigned il;
     il=cluster-2;
     il=il*sectorsPerCluster;
     il=il+dataStart;
     return(il);     
}


Great stuff!
Convert the cluster number (in this case, cluster 0x0002) into a sector (in this case, because clusters start from 2 - it's an anomaly of the FAT16 format - our first cluster is also the first sector where the data starts. We've already calculated this value)

"The actual data starts at sector 615 + 32 = 647"

If we jump to sector 647 and start reading back the data, we find that there is, indeed, data in there!
But with a file that's 613,955 bytes long, it's not all going to fit into a single cluster (one cluster is 32 sectors and each sector is 512 bytes, so that's only 32x512 = 16,384 bytes - 16kb)

So where's the rest of the data?
That's where the FAT table comes in!

Firstly, take the cluster number and double it. That's the same as bit-shifting the entire value one place to the left. In our example, our starting cluster was 0x02 so we double this and end up with 0x04
This tells us where in our FAT table to find the next (two-byte) cluster number.

Since the FAT tables themselves are written across a number of sectors, we need to convert this cluster_doubled value into a sector and byte offset, to read the actual "next cluster value" back.

Divide the cluster_doubled value by 512 to get the sector number
The remainder is the byte offset.
In our example, this gives us sectors zero, byte offset 4
So we want the first sector (sector zero) in our FAT table, fourth and fifth byte

Since the FAT table begins at sector 143, we add zero to this, open the sector (using our earlier functions) and read back all 512 bytes. When we get byte four, this makes up the least significant byte of a two-byte (16-bit) value. Byte five is the most significant byte.

In fact, when we open our sd card, read back bytes four and five from sector 143, we get
Byte 4 = 0x03
Byte 5 = 0x00

This tells us that the file continues at cluster 0x0003.
Using the same technique, we open and read the data from cluster 0x0003 (sector 647 + (3-2)*sectorsPerCluster = 647 + 32 = 679)

We continue reading data from the sector(s) and calculating the next cluster where the file continues until we've either read back the entire file (total bytes read > file size in bytes) or the FAT table returns 0xFF as the next cluster (this is a special response to say "no more clusters for this file").

This is summarised in the following function (remove comments around UART calls to see what the microcontroller is actually doing when calculating next FAT clusters).


unsigned char openNextBlock(){
     unsigned short iFATSector;
     unsigned short iFATBytes;
     unsigned short iy;
     unsigned short ix;
     
     //UARTPrintLn("opening next block of data");
     
     // the cluster_number_doubled is the location in the FAT table
     // where we can find the next block of data. If this entry is 0xFF
     // it means that there's no more blocks of data, otherwise the entry
     // is the next cluster where the file continues from
     
     iFATBytes=nextFatClusterDoubled & 511;
     iFATSector=nextFatClusterDoubled>>9;
     iFATSector=iFATSector+FATStart;
     
     //UARTPrintLn("look up next cluster in FAT ");
     //UARTPrint("sector ");
     //UARTPrintNumber(iFATSector);
     //UARTPrint(" byte offset ");
     //UARTPrintNumber(iFATBytes);
     //UARTPrintLn(" ");
     
     // check the FAT tables for the next cluster for the current file
     r=sdReadBlock(iFATSector);
     for(iy=0; iy < 512; iy++){
          r=readByte();
          if(iy==iFATBytes){ix=r; nextFatCluster=ix;}
          if(iy==(iFATBytes+1)){ix=r; ix=ix<<8; nextFatCluster=nextFatCluster+ix;}
     } 
          
     // close the currently open sector
     sdSecReadStop();

     nextFatClusterDoubled=nextFatCluster<<1; // this is the same as multiplying by two!


      
     //UARTPrint("next FAT cluster ");
     //UARTPrintNumber(nextFatCluster);
     //UARTPrintLn(" ");          
     
     if(nextFatCluster==0xFFFF){          
          // if we're at the end of the block, send the end of block marker
          //UARTPrintLn("no futher fat clusters to follow");
          return(0xFF);
     }else{
          
          // open the next sector
          iSector=clusterToSector(nextFatCluster);
          sectorCount=0;
          //UARTPrint("file continues at sector ");
          //UARTPrintNumber(iSector);
          //UARTPrintLn(" ");
          
          return(0);
     }
}