Thursday, November 15, 2012

Product Review - Ikea Sunnan Solar Desk Lamp

Much like Harbor Freight Tools, Ikea is a business that I have mixed feelings about.  Both sell products at affordable prices.  Sometimes the quality is good enough to get the job done, sometimes it's surprisingly high, and sometimes you end up with the piece of shit you paid for.  Either way, they both fit into an important niche in the economy.
Recently Ikea has begun to sell some solar desk lamps called the Sunnan.  I received two of them for my birthday.  Incidentally - if you buy a Sunnan, another is donated to Unicef.  The idea behind this is that people in developing countries that don't have electricity can use their solar lamps instead of candles and oil lamps, thereby leading toward fewer house fires.
I'd say the build quality is on the high end of average for Ikea stuff.  It's made of your standard molded plastic, but it is pretty thick.  Since it is a desk lamp, this should be more than adequate.  The part that actually emits the light is mounted on a flexible stalk.

As shown below the light output from the thing is far from fantastic:


Given that the thing runs off three AA batteries, this is to be expected.  I'm no electrical engineer, but I can tell you that emitting more light would use more power, and power is a product of voltage and current.  AA batteries can only move so much current for so long.

The charging system for the lamp is pretty novel.  The battery pack + solar panel is a module that sits in the base of the lamp.  It can be removed and placed in a sunny spot to charge.


Given that I live in Oregon and it is November, "sunny" is a relative term.  Regardless, after spending the day in the window the battery packs charged enough to run the lights again for some time.

The Sunnan is an interesting product.  It isn't going to come close to replacing most of the lighting in my house, even my non-solar desk lamp.  I'm probably going to keep using it when I'm goofing around on the computer at night.  It almost feels like a proof of concept - maybe a subsequent version will be made that uses C or D cells and is brighter. 

There's also some immediately obvious hackability.  The way that the battery pack mounts into the base looks compatible with the blade terminal connectors often used in automotive wiring.  It'd be pretty easy to remotely mount the battery pack, or repurpose it for something else.

I guess you could say I'm glad I have these lamps, but I'm glad I didn't buy them either.  For every day use, they just aren't quite there.  With that said, if I was subject to an extended power outage or lived in a flavela with no electricity I would probably feel very different.

Sunday, November 11, 2012

Getting Java to talk to MySQL

Java is a very powerful,  popular, annoyingly verbose object oriented programming language. 

I don't use Java at work or for personal programming (LAMP stuff does what I need there) but I'm slowly chipping away at my CS degree, and I found myself in the middle of a Java project for which a database was the only non-stupid solution.  Figuring out how to get it to talk to MySQL was a pretty easy process.  I'm documenting my results here.



Importing the Libraries
The needed libraries are in the java.sql.* part of the class heirarchy.  You'll need to simply put:
import java.sql*;
at the top of your code.  You'll also need to either have mysql.jar in your CLASSPATH or add it to your build path.  Eclipse can handle this automatically for you, and I'm willing to bet most other IDEs can do the same.

Connecting to the Database

Creating a connection to the database is quite simple.  You simply need to know the host on which MySQL is running, the name of the database, and the username and password.  The example below illustrates this:

try {
            String host = "127.0.0.1";
            String dbName = "baseOfData";
            String username = "sqlUsername";
            String password = "sqlPassword"; 
            String hostUrl = "jdbc:mysql://" + host + '/' + dbName;
            dbConn = DriverManager.getConnection(hostUrl, username, password );       
        } catch (SQLException ex) {
            //Handle the errors
            System.out.println("SQLException: " + ex.getMessage());
            System.out.println("SQLState: " + ex.getSQLState());
            System.out.println("VendorError: " + ex.getErrorCode());
        }

If connecting too the database fails, it will throw an SQLException.  The code in the catch block should print out enough information for you to figure out what went wrong.

Executing Queries
You can prepare and execute queries from Java, just like any other programming language.    Simply building and executing a query looks like this:

PreparedStatement sqlStatement = dbConn.prepareStatement(
                    "select p.id, p.name, p.address, p.city, p.state, p.zip, sum(s.cost) " +
                    "from services_provided sp join providers p on p.id = sp.provider_id " +
                    "join services s on sp.service_id = s.id group by p.id"
                    );
ResultSet results = sqlStatement.executeQuery();


Please note that this (and all examples) should be done in a try block.

Java supports bind variables as well.  To use bind variables you build the query with wildcards, set them, then run the query as shown below:

PreparedStatement sqlStatement = dbConn.prepareStatement(
                "update services set name = ?, cost = ? where id = ?"   
);
sqlStatement.setString(1, serviceName);
sqlStatement.setFloat(2,cost);
sqlStatement.setFloat(3, id);
sqlStatement.execute();


Getting Data Back
Getting data out of the database is quite straight forward as well.   You create a result set from the query output, which you can iterate through.  The results object will have a variety of get methods (getInt, getString, etc) for extracting the needed data as shown below:

PreparedStatement sqlStatement = dbConn.prepareStatement("select * from services");
ResultSet results = sqlStatement.executeQuery();
while (results.next()) {
                Map <String,String> service = new HashMap<String,String>();
                service.put("id", Integer.toString(results.getInt(1)));
                service.put("name", results.getString(2));
                service.put("cost", Float.toString(results.getFloat(3)));
                services.add(service);
}


Conclusion
Getting data in and out of MySQL in Java is pretty much like it is everywhere else, except more heavily object oriented than in most languages I am used to dealing with.  Despite their differences, programming languages are all more or less the same.  This is why I think it is important to focus on concepts, rather than implementations.  

Sunday, September 16, 2012

RTL2832U SDR Logging Tool

A while back I posted about the fact that some people far smarter than me learned that some USB TV tuner dongles could be used as software defined radio receivers.

This weekend I finally had time to cook up some code that used the dongle to sweep across a given range of frequencies and record the strength of the signals received.

There are two parts to the tool.  The first is the logger, which does the actual reading and storage of the data.  The second is the plotter, which creates a graphical representation of the data points which have been stored.  We will first start with the plotter.

redacted@awesomecomputer:~/sources/pyrtlsdr$ ./freqLogger.py -h
usage: freqLogger.py [-h] [-s START_FREQUENCY] [-e END_FREQUENCY]
                     [-g GAP_START] [-f GAP_END] [-i INCREMENT]
                     [-d DESCRIPTION] [-m MINUTES]

optional arguments:
  -h, --help            show this help message and exit
  -s START_FREQUENCY, --start_frequency START_FREQUENCY
                        starting frequency for sweep
  -e END_FREQUENCY, --end_frequency END_FREQUENCY
                        ending frequency for sweep
  -g GAP_START, --gap_start GAP_START
                        start of band gap
  -f GAP_END, --gap_end GAP_END
                        end of band gap
  -i INCREMENT, --increment INCREMENT
                        frequency increment for loop
  -d DESCRIPTION, --description DESCRIPTION
                        Description for report
  -m MINUTES, --minutes MINUTES
                        Number of minutes to run scan
redacted@awesomecomputer:~/sources/pyrtlsdr$




If started with no options, the logger simply loops through those frequencies (in 1 MHz increments) which it can tune to, and logs the signal strength in the database.  Please be aware that these values are based upon what my dongle can do, and they vary somewhat.  The frequency ranges and band gap can all be set via command line arguments (or by simply editing the file, since it is written in Python).  If I wanted to scan 162 through 174 MHz for 20 minutes  I would simply run:

 redacted@awesomecomputer:~/sources/pyrtlsdr$ ./freqLogger.py -s 162 -e 174 -m 20
Found Elonics E4000 tuner


The script would  run for 20 minutes, then stop.

The plotter is quite easy to use as well.  Its options are as follows:

redacted@awesomecomputer:~/sources/pyrtlsdr$ ./reportPlotter.py -h
usage: reportPlotter.py [-h] [-r REPORT_ID] [-l] [-t] [-m MIN_FREQ]
                        [-n MAX_FREQ] [-s SAVE]

optional arguments:
  -h, --help            show this help message and exit
  -r REPORT_ID, --report_id REPORT_ID
                        report id to plot
  -l, --list_reports    list reports
  -t, --time_plot       plot signal strength vs time
  -m MIN_FREQ, --min_freq MIN_FREQ
                        minimum frequency for graph
  -n MAX_FREQ, --max_freq MAX_FREQ
                        maximum frequency for graph
  -s SAVE, --save SAVE  save graph to file (png)

Each run of the logger is listed as a report.  To list the reports currently stored in the database, execute the plotter with the -l switch.

redacted@awesomecomputer:~/sources/pyrtlsdr$ ./reportPlotter.py -l
Report Id   Minimum Frequency   Maximum Frequency  Increment   Bandgap Minimum   Bandgap Maximum Description
       16          162.000000          174.000000   1.000000       1089.000000       1252.000000 Generic Report     
       15          406.000000          420.000000   1.000000       1089.000000       1252.000000 Generic Report     
       14          406.000000          420.000000   1.000000       1089.000000       1252.000000 Generic Report     
       13          406.000000          420.000000   1.000000       1089.000000       1252.000000 Generic Report     
       12          406.000000          420.000000   1.000000       1089.000000       1252.000000 Generic Report     
       11          406.000000          420.000000   1.000000       1089.000000       1252.000000 Generic Report     
       10          566.000000          574.000000   0.001000       1089.000000       1252.000000 Scan 566 to 774    
        1           52.000000         2176.000000   1.000000       1089.000000       1252.000000 initial scan     
  

 Two types of reports are supported, signal strength vs frequency, and signal strength vs time.  Please be aware that strength vs time is probably only useful for a very narrow range of frequencies.

Signal Strength vs Frequency
Signal Strength vs Time
The code can be downloaded here.
In closing I must say that I actually do not know anything about digital signal processing at all.  The method I use to read the signal strength is from a script found here.    None the less, areas where high signal strength are reported correspond to known broadcasts, so I think this is correct information.  This is also one of the first actually useful things I have ever done with Python, so it is highly likely that I have done some things that would be frowned upon by the Python community.  Either way, I think I have put something useful together.




White IPA - Taste Test

The white IPA I blogged about previously is now drinkable.  It isn't half bad either.

There's a nice citrus taste there because of the orange peel, as well as the "grassy" taste common to a lot of Belgian beers.  Unfortunately I think I overdid the hops a little.  I'm going to try backing off on the AAUs a little bit next time.  I'm also thinking about trying a couple of varieties of bittering hop to add some complexity.

Regardless, I think its pretty good for the first iteration of a new recipe.

Tuesday, July 31, 2012

White IPA Recipe

Not too long ago the folks at Deschutes Brewing out in Bend cooked up a White IPA, which is a hybrid of Belgian style white ale and India Pale Ale.  I liked it, quite a bit actually.  When the time came to make another beer, I decided to take a crack a recipe of my own.
I need to say at this point that I have not actually tasted this beer.  I actually just brewed it yesterday.  Anyway, here we go.

Ingredients:
  • 2 pounds Pilsner malt
  • 1 pound uncracked flaked wheat
  • 1 pound uncracked flaked oats
  • 2 pounds Brewer's Gold light DME
  • 4 pounds wheat DME
  • 20 AAUs Columbus hops (bitter)
  • 4 oz Cascade hops (aroma, split in half)
  • 0.5 oz curacao sweet orange peel
  • 11 oz light Belgian candi sugar syrup (this just happened to be how much I had)
  • Wyeast 3944 or some other Belgian ale yeast
Procedure
  1. Steep the grains in 1 gallon of 150 degree Fahrenheit water for 30 minutes.
  2. Rinse the grains in another gallon of 150 degree water.
  3. Dilute steeping and rinsing water to 3 gallons and bring to a boil. 
  4. Stir in the barley extract and add the bittering hops.  Boil for 45 minutes.
  5. Add the wheat extract, orange peel, and 2 ounces of the aroma hops, boil for 15 minutes.
  6. Pour into fermenter, dilute to 5 gallons, chill to pitching temperature, and pitch yeast.
  7. Rack to secondary when krausen falls and dry hop with the remaining Cascade hops.
After this is bottled and conditioned I'll update the post.

Friday, July 27, 2012

World's Cheapest Software Defined Radio (SDR)

How it began
Somewhere I read about using a cheap USB HDTV dongle for a software-defined radio receiver.  The dongle needed to be built with a RTL2832U chipset and an E4000 tuner.  The thing works from 62 MHz to around 1.7 GHz.  There's also a somewhat risky modification that allows it to pick up the HF bands, but I haven't yet tried that. 
I found one on eBay for the outrageous price of $17.  The downside is it took about three weeks to show up.

Appearances can be deceiving

After I made sure it indeed showed up on the USB bus I followed the following steps, gleaned from various blogs.  As always, I did all this stuff in a Linux environment , but it can be done under Windows or Mac OS.  Doing this stuff on a Mac is probably pretty similar.

Compile and install rtl-sdr
You will need the libusb dev headers.  If you're using a Debian based system, simply run apt-get install libusb-1.0-0-dev.

 Clone the git repository with  git clone git://git.osmocom.org/rtl-sdr.git
Make a build directory and enter it
mkdir rtl-sdr/build
cd rtl-sdr/build
Create the makefile
cmake ../
Build and install rtl-sdr
make
make install
Rtl-sdr will now be built in /usr/local.  At this point, you should be able to test the dongle.   For some reason $LD_LIBRARY_PATH was unset on my system, and there was an issue with the permissions for the USB device as well.  I ended up running as root and setting the $LD_LIBRARY_PATH

 root@gregor:~/sources/rtl-sdr/build# export LD_LIBRARY_PATH=/usr/lib:/usr/local/lib:/lib
root@gregor:~/sources/rtl-sdr/build#  /usr/local/bin/rtl_test
Found 1 device(s):
  0:  Generic RTL2832U (e.g. hama nano)

Using device 0: Generic RTL2832U (e.g. hama nano)
Found Elonics E4000 tuner
Supported gain values (18): -1.0 1.5 4.0 6.5 9.0 11.5 14.0 16.5 19.0 21.5 24.0 29.0 34.0 42.0 43.0 45.0 47.0 49.0
Reading samples in async mode...



Compile gnuradio
Most software for the dongle depends upon GNU Radio, so you must install it.  Patch Von Braun has built a shell script which will compile gnuradio for you, if you're running a Debian based system.  You can get it here.


redacted@gregor:~/sources$ wget http://www.sbrac.org/files/build-gnuradio
--2012-07-25 18:39:00--  http://www.sbrac.org/files/build-gnuradio
Resolving www.sbrac.org (www.sbrac.org)... 174.142.32.20
Connecting to www.sbrac.org (www.sbrac.org)|174.142.32.20|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 29181 (28K) [text/plain]
Saving to: `build-gnuradio'

100%[====================================================================================================================================================================================================>] 29,181      97.8K/s   in 0.3s   

2012-07-25 18:39:01 (97.8 KB/s) - `build-gnuradio' saved [29181/29181]
redacted@gregor:~/sources$ chmod a+x build-gnuradio

redacted@gregor:~/sources$ ./build-gnuradio

The script will automatically take care of any dependencies and build gnuradio, with support for the Realtek dongle.  The output is quite long, so it has been omitted.   It may take some time to finish.

After the build finishes, there are  are some applications which depend upon gnuradio that you can install.


Multimode
The first SDR application I installed was "Multimode Radio Receiver".  It is just that.

Here we can see what things look like around the aircraft band.  Please note that this is with the rather lousy antenna the dongle came with.  It isn't even close to being correct for this wavelength, so it isn't really picking much up.

It should be noted that Multimode has a scan feature that although a bit cranky, is quite interesting.  I've had a problem with it starting to scan from 150 MHz, no matter what I specify i the GUI.  A fairly clunky workaround was to edit the default values (this is a Python program, so no recompile is needed).  If I have time and a patch isn't released before I do I'll probably spend some time with WinPDB

Gqrx
Another app I tried out is gqrx.  It is a little bit more polished than Multimode, but it doesn't have the scan feature.  Here it is on a local FM station.


Conclusion
This dongle is a pretty powerful tool at a pretty cheap price.  I'm going to do a followup post once I'm more familiar with doing things in GNU Radio, and if I come across any software that I find to be particularly neat.  I'm a busy man though, so no promises as to when.

Sources
I didn't do this in a vacuum, so it is only fair that I list where I learned things.


GNU Radio and librtlsdr with Realtek RTL2832U/Elonics E4000 software defined radio receiver.


RTLSDR supported hardware

Sunday, May 27, 2012

Rehabbing Old Axes

The axe may well have been the first tool humans ever developed.  Examples have been found that were made by Homo Habilis in the lower Paleolithic era, meaning that axes have been around longer than modern humans.

Various religious orders throughout history have used axes as symbols..  They have also been used as symbols of military power and authority (see the Roman fasces).  These factors have lead to axes having a place in a lot of folklore, as well as other more modern forms of mass media.

I had a couple of axes that were in pretty sorry shape.  I'm not really sure where I got one of them, and I got  the other (the double bladed one) at a garage sale for the princely sum of $2.

You can see that the handles were in pretty sad shape, and that the heads were rusted.  The double bladed axe had probably been used to chop something other than wood as well.  I removed the handles by placing the axe heads in a vise and driving them out with a hammer and a metal rod used as an ersatz punch.  The single bladed axe took a while, but the handle for the double bladed one came out after two hits.  Some moron had tried to simply glue the handle in.


I soaked the heads in old motor oil (I'd just changed the oil in my car) overnight to soften up the rust.  After that I used a drill-mounted wire brush and orbital sander to clear the rust off.



I then sharpened the heads with an angle grinder and belt sander, and applied a few coats of paint.

After this, I began the rehafting process.  First the handle is inserted into he head.

The next step in the process is to drive the wedge into the notch in the end of the axe handle


After the wedge is driven into place, it is secured with a metal clip.  I had issues with the clip the handle came with bending, so I just used a fence staple.





After repeating the process on the double bladed axe, I now have two perfectly good axes.


It could be argued that I may have been better off just buying a couple of new axes and calling it a day.  It certainly would've saved me a bit of time.  None the less, I'm glad I did this.  I get tired of how disposable things are.  It felt good to take "worthless junk" and make it into a good, useful tool.

Wednesday, March 28, 2012

Reusing Threads in Perl

For all its warts, Perl is a powerful programming language that will continue to be used for some time.  If programming languages were people, Perl would be your crazy uncle with a very cluttered but very well stocked workshop.  One of its more powerful features is the threads api.

I have noticed that programs which create and join a lot of threads seem to consume more and more memory.  I'm not sure why this happens, but I think it is because the memory allocated when the threads are created isn't deallocated when they are joined.  (This is speculation).

The solution to this is to create a batch of threads which will run for the entire life of your program.  Instead of being joined and returning, they instead communicate via queues created using Perl's thread-safe Thread::Queue library.

In the name of full disclosure I need to state that I could not have done this without the pool_reuse.pl example found here. The aim of this article is to supplement the provided example by providing a more verbose explanation, as well as an example where data is received from the threads. 

Several queues are created.  First we make a queue which holds the ids of threads which aren't currently busy.   After this is done, we run through a loop where we create an input queue, an output queue, and a thread.  In our example,  the threads are for functions which add a random number to the input.  The input and output queues are passed as arguments.  The queues are assigned to values in hashes, keyed by the thread ids.

When we want to do actual work, we dequeue an available thread from the thread queue.  We'll then store which thread we are using in a data structure of some kind, and then dequeue  that thread's output queue later.  It is important to keep track of which queues we are using, because dequeue is a blocking operation.  If you try to dequeue an empty queue, it will simply sit there until something has been enqueued.  Depending upon how you've written things, that could be never.


Please see the example below:


#!/usr/bin/perl
use threads;
use threads::shared;
use Thread::Queue;
use strict;

#sentinal variable for threads
my $finished :shared = 0;
#number of threads
my $numThreads = 10;
my %inputQueues;
my %outputQueues;
my $threadQueue = Thread::Queue->new();
for (my $i = 0; $i < $numThreads; $i ++) {
    #create input queue for the thread
    my $inputQueue = Thread::Queue->new();
    #create output queue for the thread
    my $outputQueue = Thread::Queue->new();
    my $thread = threads->new(\&randomAdd,$inputQueue,$outputQueue);
    my $tid = $thread->tid();
    $inputQueues{$tid} = $inputQueue;
    $outputQueues{$tid} = $outputQueue;
}

#signal handler for clean exit

$SIG{'SIGINT'} = $SIG{'SIGTERM'} =
    sub {
        $finished = 1;
        $threadQueue->enqueue(0,-1);
    };

my @initialValues;

#fill up the array with random numbers
for (my $i = 0; $i < 10; $i ++) {
    push @initialValues, int(rand(100));
}

for (my $i = 0; $i < 10; $i ++) {
    print "$i\n";
    my @output;
    my @tids;
    foreach my $value (@initialValues) {
        #dequeue a thread
        my $tid = $threadQueue->dequeue();
        push @tids, $tid;
        $inputQueues{$tid}->enqueue($value);
    }
    foreach my $tid (@tids) {
        push @output, $outputQueues{$tid}->dequeue();
    }
    print "old value     new value\n";
    for (my $j = 0; $j < 10; $j++) {
        print "$initialValues[$j]          $output[$j]\n";
        $initialValues[$j] += $output[$j];   
    }
    print "\n";
    sleep 1;
}
$finished = 1;

foreach my $thread (threads->list()) {
    $inputQueues{$thread->tid()}->enqueue(-1);
    $thread->join();
}
exit(0);




sub randomAdd {
    #add a random number to the data input from the queue.
    #put the results in the output queue
    my ($inputQueue,$outputQueue) = @_;
    my $tid = threads->tid();
    while (! $finished) {
        #put ourselves in the queue so we are avilable
        $threadQueue->enqueue($tid);
        #pull input from queue
        my $inVal = $inputQueue->dequeue();
        if ($inVal >= 0)  {
            my $outVal = $inVal + int(rand(100));
            #enqueue data in output queue
            $outputQueue->enqueue($outVal);   
        } else {
            return;
        }
    }
    return;
}

Sunday, January 8, 2012

DIY Wort Chiller

One of the more annoying parts of the brewing process is waiting for your wort (flavored grain tea, beer to be) to cool off enough to pitch your yeast.  A device called a wort chiller allows you to greatly reduce the time spent doing this.

I'm going to do a little show and tell for the one I just built (entirely from hardware store components), but we're going to need to talk a little bit about thermodynamics first.

All materials have a property called specific heat.  This is how much energy (in Joules) which must be added or removed from a gram of the material in order to change its temperature by one degree Celsius.  For water (which even the heaviest beer consists mainly of) this is 4.186 Joules, which is a lot higher than most things.  A standard five gallon batch of beer will weigh just shy of 19 kilograms.  In order to get it down to yeast pitching temperature you will be trying to lower it from  just below 100 Celsius to around 24 Celsius.  Simple arithmetic dictates that we need to remove about 6 million Joules from your wort.

The other thing about thermodynamics is how heat behaves.  It flows from the areas with the most heat to those with the least until it is evenly distributed throughout the material.  This is why putting ice in your drink cools it off, and why the ice melts.  We're going to build a device to insert into our wort that will absorb heat from it, and carry that heat away.  This will be done by running water through tubing which has been submerged in the wort.

This is a 20' section of 3/8 copper tubing, purchased at a nationwide hardware store that rhymes with Gnome Repo.  My girlfriend and I wrapped it around our kitchen fire extinguisher (it was a two person job).  Enough tubing was left out to allow it to hang over the edge of the fermenter bucket.  We probably could've made it more uniform, but considering that neither of us had ever worked with copper tubing before I think we did a pretty good job.

Now that I had a really cool copper coil, I had to set it up so I could run some water through it.

Here we have a 3/8" Ander-Lign compression fitting attached to the end of the tubing.  A 1/2" pipe nipple then connects the connector for a garden hose.  The Ander-Lign fitting does not require a compression sleeve, you simply fit it to the tubing and apply torque.


Another Ander-Lign fitting is attached to the opposite end of the tubing.  It has a 1/2" to 3/4" adapter installed, so a garden hose can be attached to the output of the wort chiller.  This will allow the water to be used for other purposes (waste not, want not) or simply carry it away from the area.

While testing the chiller for leaks, I found it to be very cold to the touch.  I sincerely hope that it will significantly reduce the time spent waiting for my wort to cool.