Monday, November 18, 2013

Halloween Milling

A few years ago I bought a cheap CNC mill from China. It's actually a "CNC engraving machine", but it's actually robust enough so that it can mill wood and soft metals such as aluminum. Ḯ've been using it to build electronics prototypes, both for milling PCBs and for milling enclosures.

To control the CNC mill I have been using LinuxCNC (formerly known as EMC2). LinuxCNC takes a toolpath written in G-code which says how the milling tool should move, and translates those into the electronic signals that drive the motors on the mill.

For PCB milling I've been using a tool called pcb2gcode which takes gerber files produced by a PCB CAD program such as Eagle and produces G-code. It works really well and makes it possible to quickly testing simple electronic designs.



For enclosures I have mostly been bying ready-made enclosures and then written a bit of G-code by hand to mill holes in them. I've also been milling wood and plastics for simple stuff such as this lid.



Writinga G-code by hand is a very tedious job, anything more complicated than a few holes requires a lot of work. There are a lot of tools and meta-languages for generating G-code from other languages. I wrote my own little Python library for generating G-code and it turns out that the Axis GUI for LinuxCNC can actually load and run Python programs and execute the G-codes that are printed by the program. But even with all these tools or meta-languages it's still quite tedious to generate the toolpaths by hand.

It would be even nicer if there was a way to create a 3D model in a tool such as OpenSCAD or Blender and then magically let a tool generate G-code, a toolpath which tells the mill how the tool should move to create a physical object which looks like the model. Most 3D modeling tools can export to a standardised interchange format called STL and there are lots of tools which can read STL and generate toolpaths.

Most of these tools are proprietary though and the cost ranges from expensive to insanely expensive. Most of them only run on Windows and I prefer to use Linux and anyway I like open source, so I would prefer to use an open source toolpath generator if possible. There are a bunch of those, but most are at the "alpha" level and nowhere close to being usable. The most mature open source toolpath generator I have found is PyCAM. Unfortunately PyCAM and I don't really get along, I don't like the toolpaths it generates and last time I tried, it was really, really slow. My guess is that one for PyCAM being so slow is that it tries to be very generic and handle models and milling tools of almost any shape. Algorithms to calculate a toolpath for an abitrary 3D shape around an arbitrary 3D model are complex and expensive.

For a long time there have been this thoght at the back of my head that "there must be an easier way". For almost everything I want to mill, I'm going to use a cylindrical tool. With a cylindrical milling tool, the toolpath generation problem is reduced to 2.5D, that is, for each position X and Y the tool is allowed to reach a certain depth Z. This 2.D problem ought to be a lot easier to solve than the generic 3D problem.

A fairly simple strategy of milling 2.5D shapes would be to slice up the 3D model into 2D layers. The algorithm would then start from the top, and remove material for each 2D layer until there is no more material to remove. This is called waterline machining. It might not be the fastest way to things, but it should be fairly foolproof.

For removing material there are lots of ways to do it. The simplest way is to just move back and forth in a zig-zag pattern. But there are much better ways to do it, to reduce the wear on the milling tool it's preferable to keep a constant load on the tool, i.e. cut with the same side of the tool at the same depth and at the same speed all the time. The most important thing is to avoid is rapid load changes such as cutting 90 degrees into a wal. This article att BobCAD-CAM shows some of the toolpah options that used. Option 3, the High Speed Machining (HSM) toolpath, is the best since it avoids any sharp corners and each cut is very smooth.

I have been toying with algorithms like these for a few years but have never gotten anywhere. But a few weeks ago just before Halloween I tried a slightly different approach. The goal was to find an algorithm which would remove material from a 2D outline and do it using the same side of the tool to perform all cuts and which would try to keep the cuts at a constant width.

What I did was to split the toolpath generation into four steps.

1. Take the model and shrink it by the milling tool radius. This way the algorithm can ignore the tool with for the rest of the calculations, instead it only have think about where the tool can move.

2. Find the center of largest circle that can be inscribed in the model. To do this just shrink the model until there is nothing left and use the center of the last polygon as the starting point.

3. Start cutting a spiral from the starting point outwards until the spiral intersects the outline. For each 360 degree turn the radius of the spiral grows by the cut width.

4. Cut away the rest of the material. Start by creating a polygon with the the material that has already been cut away, this will roughly be the convex hull of the spiral. Grow the polygon by the cut width and then clip it with the model. The difference between the polygon of already removed material and the grown and clipped polygon are a number of polygons with material that is possible to remove. Choose one of them, mill away the material, add the polygon of just removed material to the big polygon of removed material and start over again until there is no more material to remove.

I started out by using the Python port of the Clipper library to do the shrinking, growing and clipping but switched to Shapely after a while because I needed some function that wasn't available in Clipper. A function that I ended up not using in the end anyway, but by then I couldn't be bothered to switch back.

This actually turned out to work quite well. Because it was Halloween I decided to do a small test with a witch silhouette I found. I converted it by hand from SVG to a bunch of coordinates (and managed to flip the image horizontally and lose a few parts of the broom on the way).

The following video shows the algorithm running.


Since this seemed to work so well I quickly added some functions to generate G-code and then used LinuxCNC to run the G-code on the mill. And what do you know, it actually worked quite well.


The video is speeded up 10 times, in real life it took about 20 minutes to run.  The algorithm video and the actual milling video differ a bit in the cuts since I tweaked the algorithm slightly in between.

Of course this is just a quick proof of concept hack to see if the algorithm would work at fall, but it does look rather promising.

There are lots of things to do though to bang this into shape so that it is actually useful.

The algorithm makes a few mistakes where removes too much material at the same time. It really should try to find a way of smoothly moving into each cut.

The algorithm does not support multiple pockets or pockets with holes.

The algorithm only cuts one layer in 2D, to be useful for milling it needs to be extended to 2.5D.

Yet another pre alpha not even close to production ready piece of software for generating toolpaths. Probably not that interesting, but if anyone wants to see the source code, drop me a line.

Friday, November 15, 2013

Lifehacking

I'm a nerd, I find technology fascinating. In my career I've done just about everything with computers, from being a system administrator changing disk packs for backups to writing J2EE code or designing and building simple electronics. And just about everywhere I've seen fascinating stuff that I would like to learn more about and have had ideas about interesting things that I'd like to try out. But over the last few years I have been working full time or more and really have not had the time nor energy to do that.

So I've decided to make a bit of an experiment with my life. A few months ago one of the customer projects I was working on was coming to an end, and instead of getting a new full time contract I decided to try to work part time, one week at a customer and then one week on my own. That didn't work out too well, as soon as some former colleagues heard I was free they convinced me to work on another customer project, so I ended up working full time again. Oops. Anyway, now that project has ended, so it's time to try again.

So what am I going to do with this week on my own?

Well, one thing I'll do is to try to spread the word that I'm available for hire if anyone has any interesting problems they want solved. I like really hard troubleshooting under time pressure, a "mission impossible" in the borderland between hardware and software, for example where a customer has a problem with a device driver or new piece of hardware that just won't work reliably and the deadline is approaching rapidly. I've actually had some success in solving a few problems like this where the customer didn't know if it was a problem with the hardware or the software and was running out of ideas.
“In the fields of observation luck favors only the prepared mind.“ – Louis Pasteur
I don't always succeed, but somehow I'm quite often "lucky" and usually manage to solve the problem or at least identify the cause.

But I probably can't count on getting these kinds of jobs all the time, so I'll probably have a lot of free time on my hands. I'll try to dig up some of my old ideas and see if I can do something with them. Or maybe just spend some time writing about them on my blog and see if someone else might get inspired and do something.

One such idea I've had since Google Reader was shut down is to write my own feed reader. And when I finally did get around to it, it didn't take much more than a week to actually write something that worked. The result is Weader, a simple atom/rss feed reader for Android. This was all about scratching an itch, I didn't like any of the existing feed readers out there, so I wrote one that works the way I wanted. And it also means that I got up to speed with writing Android applications, something that I've been meaning to do for a long time.

I'll probably run out of money long before I run out of ideas, so my plan is to try this out for a few months, after that I'll probably have to go back to working full time, but who knows, it might work out. And if anyone has any interesting problems that need solving and want to hire me, drop me a line. My rates are negotiable.

Thursday, October 24, 2013

Creating Android menu icons with Inkscape

I've spent a few weeks writing a feed reader for Android, Weader and wanted to have nice little menu icons for every possible choice.  Android comes with a bunch of standard icons in the SDK and it's probably a good idea to use them to begin with so that an application will fit the standard Android look.  But I needed a few more icons.

I tried to find some instructions about how to create icons that look like the standard menu icons but the information on the Android developer pages about iconography was rather brief and in some cases flat out wrong.  The offical pages say that icons meant for a black background should be use color #ffffff with 80% opacity which is just plain wrong, if you try to do that any white parts will end up being too bright and what to do about black areas in your icons?

After a bit of reverse engineering of the existing icons, writing a bit of Python Imaging Library code to extract the alpha layer, poking at the pictures with Gimp and a lot of fiddling around in Inkscape I finally managed to produce a couple of icons that I'm fairly happy with.  So to spare anyone else the same problems, here's how I finally generated my icons.

Icons in Android must be PNG files and they should be provided in multiple sizes to fit devices with different screen resolutions.  The "active area" is the area that should be covered by the actual objects in the icon, there is supposed to be a bit of empty space around.

ResolutionDPIMenu Icon SizeActive Area
ldpi12024x2418x18
mdpi16032x3224x24
hdpi24048x4836x36
xhdpi32064x6448x48
xxhdpi48096x9672x72

Actually, the ldpi icons in Android seem to be 36x36 which is strange since if I calculate the proper size based on the DPI it comes out as 24x24.  Anyway nobody uses ldpi any more so I'll just ignore that and use 24x24.

Inkscape's native file format is SVG, Scalable Vector Graphics, which is an open standard for vector graphics, so that is the format I'll use.  The resolution for SVG files is hardcoded to 90 DPI (dots per inch).  This doesn't match the Android resolutions very well, I just decided to pretend I did everything in the hdpi resolution then fix things ups when exporting an image in PNG format later on.

So, here's what I did.

First I created a new image in Inkscape and then selected File -> Document Properties and set the image size to 48x48 pixels to match the menu icon size for the Android hdpi resolution:


To make things a bit easier for me I switched to the Grid tab and set up a 1x1 pixel grid with major lines every 8 pixels.  Time to start drawing:


I needed quite a bit of experimentation to get about the same line weight and color as the stock Android icons, but finally managed to get something that looks decent.

Select the Object -> Fill And Stroke menu.  Set the fill to white (#ffffff) and the stroke to black (#000000) and then select a stroke width of 1.25 pixels and a blur factor of 2.5.

The final touch is to set the layer opacity to 60%.


Export the drawing using File -> Export Bitmap.  First press the Page button to use the page boundaries as the limits for the bitmap and then set the size to the icon size you want, in my case I chose 48x48 pixels for hdpi. And then press export to create the bitmap.


It's possible to use Inkscape from the command line to automate the creation of the PNG files.  Put the SVG file in a directory called "art" in the project and then run the following shell script:
while read dir dpi; do
inkscape 
    --export-area-page --export-dpi=$dpi \
    --export-png=$dir/ic_check.png ic_check.svg
done <<EOF
../res/drawable-ldpi 45
../res/drawable-mdpi 60
../res/drawable-hdpi 90
../res/drawable-xhdpi 120
EOF
The trick here is to use the correct resolution.  Since the SVG file is in 90 DPI and is drawn for the hdpi resolution, I just have to scale the requested resolution to get the correct PNG image size.  This trick also means that I an use the same script for my launcher icon which is supposed to be 72x72 pixels in hdpi.  Draw it at that size in Inkscape and it will automatically be exported at the correct sizes for a launcher icon. 

So here's the result, ldpi, mdpi, hdpi and xhdpi icons.  The top row are my new icons, the bottom row are the original Android icons.
The other icons are very, not perfect, but they'll do.  I am a bit confused though, the image here was composed in Gimp and the colors look quite different.  When I tested this on an actual Android device the color for the white part of the icon was identical.   And as you can see, the ldpi icon in stock android is completely different, it's using the pre-Honeycomb style for icons, but I'll ignore that and use the same theme for all different resolutions of my icons.

Trying to create an icon which is identical to an existing android icon is probably a bit unnecessary, but the nice thing about having a nice little icon in SVG format is that it's very easy to modify it to create the extra icons I needed in my application, all with the same look and feel.

By the way, as you can probably guess, the icons are used to mark articles as read or unread.  I'm not totally happy with these symbols, the check mark and the cross don't feel right, on the other hand I can't come up with any better ones.  If you have any ideas for icons that might fit better, please drop me a line, I'm always open for suggestions.

Weader - A simple atom/rss feed reader for Android

Ever since Google cancelled Google Reader I've been looking for a new feed reader.  I haven't found one I like so far.  I've tried Feedly, Newsblur, Tiny Tiny RSS and a bunch of others but none of them really did what I wanted, most tried to do too much, all I wanted was a simple and lean feed reader for Android that I could use while commuting to work.  Then I found FeedGoal.  I didn't like the user interface FeedGoal either, but it is open source and had a fairly nicely partitioned backend which would probably be possible to reuse.

So I've been playing around with FeedGoal for a few weeks and ended up writing a completely new user interface for it that I'm pretty happy with.  I've called my application "Weader", a play on my last name which begins with a W and "reader".  Imagine Elmer Fudd trying to pronounce "reader", that's how you pronounce it.

The application doesn't do anything fancy at all, all you get is a list of feeds and when you click on a feed you'll get a list of articles in that feed.  Click on the article and you'll get a full page with the contents and you can swipe left and right to go the next and previous articles.  And that's all there is.  No cloud services, no subscriptions, no sharing of links, no webapps, just reading feeds on an Android phone.

If anyone wants to try it out it's available on Google Play.  And oh, have I mentioned that it's open source and that all the sources can be found on GitHub?

Saturday, August 3, 2013

Coaxial Cables

It's been a long time since I wrote anything here so I guess it's time to write something.  A warning though, this post will talk about coaxial cables, so those with a low tolerance for boredom can stop reading now.

A few years ago I bought a TDR oscilloscope and wrote a bit about how you can use it to measure the performance of different kinds of cable.  So I went out and bought a bunch of different coaxial cables and tried to measure the RF performance of them.  The idea was to see how much difference the cables make before buying half a dozen cables to use in my lab.

My oscilloscope also has a function for Time-domain transmissiometry (TDT).  This functions uses the same pulse generator as the TDR function, but the cable is connected between two ports on the scope and instead of looking at the reflections, the scope will measure the signal that comes out the other end.  The pulse has a 250mV amplitude and a 25ps rise time and for a perfect cable what would be what the scope would show at the other end, but with real cables there will be distortion of the signal.

A square wave is composed of all the odd harmonics of the fundamental frequency for the square wave.  A first approximation of a square wave is just a sine wave, and by adding higher frequency harmonics the shape will get closer and closer to a perfect square wave with vertical edges that are infinitely short.


In the physical world is not possible to have harmonics with infinitely high frequencies, so all actual electrical signals will only approximate as square wave and will have a bit of ringing and non-zero rise and fall times.  The higher the bandwidth of the system the faster rise and fall times it will have and the closer it can get to the ideal square wave.

As a rule of thumb for analog oscilloscopes, the bandwidth neccesary to show a certain rise time is:
bandwidth * risetime = 0.45

So a 25ps risetime requires about 0.45 / 25ps = 18GHz of bandwith. 

This also shows up with cables, cables attenuate signals send through them, and the attenuation is frequency dependent.  Most cables attenuate high frequency signals more than low frequency signals and when measuring TDT this will slow down the rise time of the TDR pulse.  So a cable with higher bandwidth will generally show faster rise times.  A cable with with high bandwidth could have high total losses though, and vice versa.  A mains extension cord has horrible bandwidth but not that much losses, while a thin coax cable can have pretty good bandwidth but high resistance and losses.  Another thing to think about is the impedance of the cable, a thin and flexible cable might get bent or pinched so that the impedance varies and this can cause reflections and losses.



Without further ado, here are the contestants:


 Starting from the left, here are the results.

  1. 75 cm of RG405, a 2.2 mm diameter semi-flexible cable bought from rfsupplier.com.  Semi-flexible means that the cable is fairly stiff and not that easy to work with - you're really meant to connect the permanently and not move it around that much.  The received signal is down at 230mV at the other end, so the total losses are fairly high and the rise time is just below 30ps so the bandwidth is decent.
  2. 75 cm of RG402, a 3.6 mm semi-flexible cable also from rfsupplier.  Not as much losses as with the RG405, the received signal is 240mV and the rise time is also just below 30ps.  I guess this is to be expected, a thicker cable has slightly less resistance and less losses.
  3. 28 cm of semi-rigid cable bought from sdr-kits.net.  This was some surplus cable so I have no idea what the brand of the cable is.  I is short and semi-rigid means that it's stiff and hard to work with and can probably not be bent more than a dozen times without going bad.  It is the best cable I have though, very low losses, the received signal is at 245mV and the rise time is at 25ps, almost identical to the source.  I'm curious to how much of this performance is due to the cable being so short and how much is due to the quality of the cable.  It would be interesting to get a 25cm RG400 or RG402 cable and compare.
  4. 75 cm of RG400, a 5mm flexible cable from rfsupplier.  RG400 is specified to have a "max operating frequency" of 12.4GHz.  It's quite nice to work with since it is fairly flexible.  It did have fairly high losses with 235mV received signal and the rise time was 30ps.
  5. 75 cm of KSR195, a 5mm "low loss" cable from rfsupplier.  The cable is supposed to be a replacement for a standard cable called LMR195.  It's fairly stiff and hard to work with.  Low losses at 240mV received signal and the same 30ps rise time as most other cables.
     
  6. 65 cm of flexible cable from sdr-kits, also surplus with a Huber Suhner sticker on it. The loss was decent at 240mV but the rise time was 33ps, slightly slower than most other cables.  Nice to work with though and the angled connectors make it preferable for some tasks.  I'm also curious to how the angled connectors affect the rise time, does it make any difference or not?
  7. 75 cm of KSR420, a 6 mm "low loss" cable from rfsupplier.  Replacement for standard cable LMR240.  Fairly stiff and cumbersome.  Low losses at 245mV received signal and a rise time of 30ps.  There were noticeable impedance discontinuities at the SMA connector though which showed up in TDR measurements.
  8. 75 cm of KSR400, a 10 mm "low loss" cable from rfsupplier.  Replacement for standard cable LMR400.  Low losses at 245mV received signal and a rise time of 33ps.  Even stiffer and harder to bend than KSR420 and had even more impedance discontinuities in the connector.
     
  9. 50 cm piece of unspecified 2mm flexible cable which is not in the picture.  This is just some cable I had lying around.  Very thin and flexible and nice to work with.  Decent losses at 240mV but slow rise time at 35ps.
What's the result of all this?  Well, the differences were smaller than I expected, all cables are probably good up to 10GHz or so and have reasonable losses.  This informal testing was probably unfair to the low loss cables, they are meant to be used for long distances where loss is very important, testing on a 75cm piece of cable does not show off what they are good at.  I did find a data sheet for LMR400 which says that it is only specified for signals up to 2.4GHz.; according to the rule of thumb above, the 33ps for KSR400 means that for such a short length it had a bandwidth of more than 10GHz.  If I really wanted to test this cable properly I ought to buy 100m of cable and see how it performs. It's probably also kind of dumb to put SMA connectors on such cables since a SMA connector is so small compared to the diameter of the cable, using a N connector would probably work much better. 

So, if you need the best performance, buy a good (and probably expensive) and short semi-rigid cable.  Or call Huber Suhner and buy their Sucotest cable, I've used it before and yes it's expensive but it's also flexible and nice to work with; it's high performance and they will even calibrate it for you so that you know the attenuation for all frequencies up to the specified bandwidth of the cable.  I wish I could afford stuff like that nowdays.

Me, I'll probably buy a couple more cables with RG400, it's flexible nice to work with on a lab bench and has decent performanc.  I must also say that I'm quite happy with rfsupplier, I found them on eBay and they built exactly the cables I asked for at a good price and with fast delivery.  I was a bit worried about buying cables from China, but after measuring the cables rfsupplier delivered and comparing them to other variants I have nothing at all to complain about.  And I'll see if they have some cable similar to the last one in the list, since it's so thin and flexible it's even nicer to work with and for signals up to 1GHz or so it's probably quite good enough.

Monday, April 15, 2013

NFC, vad är det?

Jag har just skaffat en ny Android-telefon med stöd för "NFC".  NFC betyder "Near Field Communication" eller på ren svenska trådlös överföring av information mellan två prylar som är nära varandra.  På svenska brukar man annars prata om beröringsfria kort.  Ett exempel är kortet som används för att åka med Stockholms Lokaltrafik.

Fast NFC är rätt luddigt, det handlar mer om marknadsföring och jag är mer intresserad av tekniken under.  Eftersom jag sitter fast på Arlanda just nu och väntar på ett försenat flyg så har jag passat på att läsa på lite.

Tydligen så stödjer Androids NFC fyra olika olika tekniker för kommunikation med beröringsfria kort:

NfcA - ISO 14443 Type A.  En radiokodningsstandard för hur man skickar data på 13.56MHz och som brukar användas för beröringsfria kort.  Längsta avstånd mellan läsare och kort brukar vara kring 5-10c och man kan få en överföringshastighet på några hundra kilobit/sekund.  Mifare är baserat på 14443 Type A.  Jag jobbat en hel del med Mifare som används i passersystem.  Mifare används också i en en massa betallösningar, bland annat Access-korten som används i Stockholms lokaltrafik, Oyster Card i Londons lokaltrafik och (upptäckte jag idag) tio-kortet på Arlanda Express.

NfcB - ISO 14443 Type B.  En annan radiokodningsstandard som är väldigt lik Type A men lite annorlunda.  "Det som är så bra med standarder, alla har en."  Den stora fördelen med Type B är att man tydligen kan överföra mer energi till kortet än vad Type A kan, så man kan göra mer intressanta saker i korten med Type B.  Det finns en standard som heter iClass som för det mesta använder Type B.

NfcV - ISO 15693.  Ytterligare en radiokodningstandard för 13.56MHz.  Till skillnad från ISO 14443-varianterna så kan den användas på längre avstånd, ända upp till någon meter.  Men man får betydligt lägre överföringshastighet, mellan 5-25kilobit/sekund.  Så för passersystem där man vill kunna öppna en dörr genom att komma nära den så vill man använda ISO 15693 istället för 14443.  Men man har inte tillräckligt med överföringshastighet för att kunna göra speciellt avancerade saker.  I iClass så ingår även ISO 15693.

NfcF - FeliCa.  En standard från Sony i Japan för olika beröringsfria betalkort som också jobbar på 13.56MHz.  Ganska lik ISO 14443 Type A/B men lite annorlunda.  FeliCa var nästan på väg att bli standardiserad som ISO 14443 Type C men det blev inget.  "Det som är så bra med standarder..."  Används för kollektivtrafik på en massa ställen i Asien som Bankok och Hong Kong.  Singapore EZ-Link använde tydligen Felica förut men har bytt till Mifare nuförtiden.

Bara för att vara någorlunda komplett så ska jag väl också nämna att det finns en äldre standard för beröringsfria kort som kallas för "EM Marin" som jobbar på 125kHz.  Överföringshastigheten är väldigt låg och det finns nästan ingen säkerhet, men det är robust och kan fungera på flera meters avstånd.  Om man har beröringsfria kort i huset där man bor så är det förmodligen EM Marin även om det börjar dyka upp Mifare även där.  Vad jag kan se så stödjs inte EM Marin av Android.