Sunday, 9 September 2012

Playing with a wiimote

Intro

I've got some plans for using a wiimote an an interface to a project I'm working on. I'm particularly keen to use the MotionPlus capabilities of the newer wiimotes to determine its orientation, but to get that to work I've first got to manage to get the raw data out of the wiimote.

This post will show how to connect to and get sensor data out of a wiimote on a linux machine.

Connecting to the wiimote

The first step is to connect to the wiimote. Wiimotes communicate via bluetooth, so you'll need a computer that has bluetooth capabilities. Most laptops have bluetooth built in, otherwise you'll need to grab a USB Bluetooth dongle. You should be able to pick one up for ~$5 on ebay (just make sure it works under linux before you buy it).

Okay so once you've got bluetooth connected, we'll see if we can discover the wiimote. Press the 1 and 2 buttons at the same time on the wiimote - this will put it into discoverable mode (the lights at the bottom should flash to indicate that it is in discoverable mode). Then run the command "hcitool scan" :
rlawther@voodoo ~ $ hcitool scan
Scanning ...
    E0:0C:7F:8B:4D:77    Nintendo RVL-CNT-01

Nice, it found our wiimote. That means our bluetooth is working. Let's see if we can get some interesting data out of it.

Testing the wiimote

Ok so we've managed to connect to our wiimote, so now lets see if we can get some data out of it. Luckily for us, someone has already written a nice little GUI to interpret the data come back from a wiimote - it's called wmgui and you can install it by running "apt-get install wmgui".

To run it simply type "wmgui". Then click File -> Connect and follow the prompts.  Once you're connected you should be able to press some buttons and see them get highlighted in the GUI.

wmgui showing current state of the wiimote

Have a bit of a play and get a feel for how the sensors react as you move it around.

Note that wmgui won't display MotionPlus values, and that's what we're after. So let's go a little depper and write some python code to get data from the 'mote.

Polling the wiimote

I've tried a couple of libraries to get wiimote data in python, and I found the easiest to be cwiid. Grab it with "sudo apt-get install python-cwiid". Now we can poll the MotionPlus data with a simple script

#! /usr/bin/python 
import cwiid 
import time 

print "Press 1+2 on the wiimote" 
wm = cwiid.Wiimote() 
wm.led = 1 
wm.enable(cwiid.FLAG_MOTIONPLUS) 
wm.rpt_mode = cwiid.RPT_BTN | cwiid.RPT_MOTIONPLUS 
print "OK, connected" 

while True: 
    print wm.state 
    time.sleep(0.1)

This script polls the wiimote at around 10 times per second and dumps the data to the screen. Have a look at the "motionplus" section of the output, and see what happens as you move the 'mote around.

rlawther@voodoo dumpMotionPlus $ ./dumpMotionPlus.py 
Press 1+2 on the wiimote 
OK, connected 
{'led': 1, 'rpt_mode': 130, 'ext_type': 0, 'buttons': 0, 'rumble': 0, 'error': 0, 'battery': 74} 
{'led': 1, 'rpt_mode': 130, 'ext_type': 0, 'buttons': 0, 'rumble': 0, 'error': 0, 'battery': 74} 
{'led': 1, 'rpt_mode': 130, 'ext_type': 4, 'motionplus': {'angle_rate': (8198, 8313, 8158)}, 'buttons': 0, 'rumble': 0, 'error': 0, 'battery': 74} 
{'led': 1, 'rpt_mode': 130, 'ext_type': 4, 'motionplus': {'angle_rate': (8199, 8294, 8159)}, 'buttons': 0, 'rumble': 0, 'error': 0, 'battery': 74} 
{'led': 1, 'rpt_mode': 130, 'ext_type': 4, 'motionplus': {'angle_rate': (8195, 8284, 8167)}, 'buttons': 0, 'rumble': 0, 'error': 0, 'battery': 74} 

When the 'mote is still, the motionplus values will hang around the 8200 mark. This will vary a bit from 'mote to 'mote, so you'll need to calibrate each time you connect to a 'mote to find out its "zero" value. Also note that these values represent the current angular velocity of the 'mote - if you want its absolute orientation in space, you'll need to integrate these values over time.

Stay tuned for another blog post on how to do that ... : )

Saturday, 4 August 2012

Stove output test

To get some idea of how much heat my EverythingNice stove outputs, I did a simple test. I placed a pot of water on top of it and measured the temperature of the water each minute.

The mass of the steel pot is 308g (without the lid), and contains 650g of water. The stove was lit, and after the flame settled down the pot was placed on top.


 
The setup

  Each minute the temperature of the pot was measured with an infrared thermometer. It was measured near the corner of the pot from the inside.

Temperature vs Time

The graph from 2 -> 20min is fairly linear, so let's use that part of the graph. At 2min it was 24.8°C, at 20min it was 73.8°C.

ΔTemp = 73.8°C - 24.8°C = 49.0°C

The specific heat capacity of water is 4.18J/g.K, so the amount of energy that's gone into the water is

ΔEwater = 4.18J/g.K * 650g * 49K = 133.1KJ

And the specific heat capacity of steel is 0.47J/g.K, so the amount of energy that's gone into the steel is

ΔEpot = 0.47/g.K * 308g * 49K = 7.1KJ

So the total energy into our system is 133.1KJ + 7.1KJ =  140.2KJ

Now as

Δtime = 20min - 2min = 18min = 1080seconds

our power is 140.2KJ / 1080s = 130W

So it seems we put around 130W into our system, meaning our stove outputs at least that much. How much heat got "lost" ... I've no idea, but it gives us an idea of the sort of numbers we're looking at.



Tuesday, 10 July 2012

Simple python config

Often when I'm writing python code I'll be setting some values and think to myself "Gee, these values should really be stored in a config file". That thought is often followed by "Nah, too much effort. This is just a quick script anyhow". If there was a way of making using config files almost zero effort then I'd be more likely to use them and not have to deal with my "quick script" now being a couple of hundred lines of code and having no easy way of changing the configuration.

Python's ConfigParser module can do most of the work, but there are still some things that make it just that little bit of effort to use.

  • It doesn't know/care about types. Everything is just a string. You have to consciously call getint or getfloat etc depending on what type you want.
  • I'd prefer to just have a simple dictionary with all my values in it - config['section:key'] looks neater than config.get('section', 'key') (to me anyhow)
  • It can't deal with config files that don't have a section in them
  • If I'm working on amazingProgram.py I'd like it to default to using amazingProgram.cfg without having to explicitly tell it.
I've written a fairly simple function to get around these issues. It uses ConfigParser to read the config file, and turns it into a simple dictionary. For each value it determines if it is a int, float, bool (denoted by any of 'true', 'yes', 'on', 'false', 'no', 'off') or if none of these leaves it as a string.

You can tell it which config file to read, but if none is given it will take the name of the file containing the __main__ function, and replace the '.py' with '.cfg'. Using it is as simple as
import simpleConfig

config = simpleConfig.parseConfig()
So let's say I have a config file called test.cfg which contains
host = localhost
port = 8080
delay = 1.0
use_tcp = true

And I make a test.py with
import simpleConfig

config = simpleConfig.parseConfig()

if config['use_tcp']:
        print config['host'], type(config['host'])
        print config['port'], type(config['port'])
        print config['delay'], type(config['delay'])
When I run it I get
[rlawther@wagner tmp]$ python test.py
localhost <type 'str'>
8080 <type 'int'>
1.0 <type 'float'>
So hopefully, next time I think I should put something in a config file I'll use this rather than not bothering.

Monday, 2 July 2012

Building pyliblo on Windows using Visual C++ 2010

Python's great, I quite like liblo, and sometimes I'm forced to use Windows. I couldn't use mingw, so these 3 facts lead me to trying to get pyliblo to build on Windows using Visual C++ 2010. Feel free to follow along at home if you will ...

This will show all the errors you encounter along the way and how to overcome them. So hopefully parts of this may apply to other python modules out there as well.

Get pthreads for windows

liblo uses pthreads, so you'll need to get that first. I got mine from here, but I guess just get whatever happens to be the latest when you read this. Get the .zip version as it has precompiled DLLs in there, unless you particularly feel like build yourself. Extract the zip file to a scratch directory somewhere - I'm using d:\tmp

Build liblo

We need to build the liblo DLLs for pyliblo to use. So ...
  • If you haven't already, you'll need to install Visual C++ 2010. I installed the express edition (for free) from here
  • OK, now get the liblo source and extract it also to d:\tmp
  • Your scratch dir should now look like this
  • Folders after extacting pthreads and liblo
  • Open up a command shell (Start -> Run -> cmd) and change to the liblo-0.26\build directory. Run the command premake4.exe vs2008 :
    D:\tmp\liblo-0.26\build>premake4.exe vs2008
    Building configurations...
    Running action 'vs2008'...
    Generating vs2008/liblo.sln...
    Generating vs2008/liblo.vcproj...
    Generating vs2008/testlo.vcproj...
    Generating vs2008/subtest.vcproj...
    Done.
    
  • This has now generated our solution file for us. Back in Windows Explorer, double click on the D:\tmp\liblo-0.26\build\vs2008\liblo.sln file.
  • Because this file was generated for Visual Studio 2008, it will want to convert it to the 2010 format. Just click Next, Next, Finish.
  •  Now inside Visual Studio, first we want to change the Active Solution Configuration from DebugDLL to ReleaseDLL. There's a drop-down box near the top of the screen to do this
  • Selecting the ReleaseDLL solution configuration
  • OK, so let's try to build these liblo DLLs. Right click on the "liblo" text in the "Solution Explorer" and select "build".
  • Look at the output of the build command in the output window at the bottom. You should see that it failed with errors looking like
    d:\tmp\liblo-0.26\src\lo_types_internal.h(31): fatal error C1083:
    Cannot open include file: 'pthread.h': No such file or directory
  • OK, so it can't find the pthread headers, we'll need to let it know where they are. So, right click on the liblo solution again, and select the properties option.  In the properties window go to Configuration Properties -> C/C++ -> General  and find the Additional Include Directories entry. We need to add ;..\..\..\Pre-built.2\include. Note the semicolon at the start to separate it from the previous directory
  • Adding an include directory
  • Try and build again. This time it will fail with
    LINK : fatal error LNK1104:
    cannot open file 'pthreadVC2.lib'
    OK, so it compiled fine, it's the linker that now complaining. We need to tell the linker where it can find the lib file. Again right click on the liblo solution and select properties. This time we want to edit the Configuration Properties -> Linker -> General -> Additional Library Directories entry and add the string ;..\..\..\Pre-built.2\lib\x86 (building for 64 bit OSs is left as an excercie for the reader)
  • Build again - this time it should work and you'll see that ever so pleasing output
  • ======= Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped =======
  • Great, now you've got liblo DLLs - they'll be in the D:\tmp\liblo-0.26\lib\ReleaseDLL folder.
  •  

Build pyliblo

OK so this is the part we've all been waiting for, we actually get to build pyliblo.
  • Grab pyliblo from here and extract as before.
  • Again we'll get another command shell and try to compile as we usually would for a python module by running python setup.py build
  • D:\tmp\pyliblo-0.9.1>python setup.py build
    running build
    running build_ext
    building 'liblo' extension
    error: Unable to find vcvarsall.bat
    
  • Hmm, okay, python is set up to use Visual Studio 9 (ie. 2008) so it can't find the 2010 files. We can fix that by running
    SET VS90COMNTOOLS=%VS100COMNTOOLS%
  • Try again:
    D:\tmp\pyliblo-0.9.1>python setup.py build
    running build
    running build_ext
    building 'liblo' extension
    creating build
    creating build\temp.win32-2.7
    creating build\temp.win32-2.7\Release
    creating build\temp.win32-2.7\Release\src
    D:\apps\Microsoft Visual Studio 10.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS- /
    DNDEBUG -Id:\python\python27\include -Id:\python\python27\PC /Tcsrc/liblo.c /Fob
    uild\temp.win32-2.7\Release\src/liblo.obj -fno-strict-aliasing -Werror-implicit-
    function-declaration -Wfatal-errors
    cl : Command line error D8021 : invalid numeric argument '/Werror-implicit-funct
    ion-declaration'
    error: command '"D:\apps\Microsoft Visual Studio 10.0\VC\BIN\cl.exe"' failed wit
    h exit status 2
    
  • At least it's found the compiler, but now we're getting compiler issues. There's a bunch of flags being passed to the compiler that it doesn't understand (such as -Werror-implicit-function-declaration) ... we'll just remove them. Open up setup.py in your favourite text editor. Look for the flags that cause the issues ... there they are
    ext_modules = [
        Extension(
            'liblo',
            [use_cython and 'src/liblo.pyx' or 'src/liblo.c'],
            extra_compile_args = [
                '-fno-strict-aliasing',
                '-Werror-implicit-function-declaration',
                '-Wfatal-errors',
            ],
            libraries = ['lo']
        )
    ]
    
    Just remove all the extra_compile_args ...
    ext_modules = [
        Extension(
            'liblo',
            [use_cython and 'src/liblo.pyx' or 'src/liblo.c'],
            extra_compile_args = [],
            libraries = ['lo']
        )
    ]
  • Sweet, let's try to compile that.
    D:\tmp\pyliblo-0.9.1>python setup.py build
    running build
    running build_ext
    building 'liblo' extension
    D:\apps\Microsoft Visual Studio 10.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS- /
    DNDEBUG -Id:\python\python27\include -Id:\python\python27\PC /Tcsrc/liblo.c /Fob
    uild\temp.win32-2.7\Release\src/liblo.obj
    liblo.c
    src/liblo.c(221) : fatal error C1083: Cannot open include file: 'lo/lo.h': No su
    ch file or directory
    error: command '"D:\apps\Microsoft Visual Studio 10.0\VC\BIN\cl.exe"' failed wit
    h exit status 2
  • Right, it can't find the liblo headers. Let's show it where to look. We'll point it at the pthread headers too while we're at it.
    ext_modules = [
        Extension(
            'liblo',
            [use_cython and 'src/liblo.pyx' or 'src/liblo.c'],
            extra_compile_args = ['-ID:\\tmp\\liblo-0.26', '-ID:\\tmp\\Pre-built.2\\include'],
            libraries = ['lo']
        )
    ]
    
  • Let's see how this goes
    D:\tmp\pyliblo-0.9.1>python setup.py build
    running build
    running build_ext
    building 'liblo' extension
    D:\apps\Microsoft Visual Studio 10.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS- /
    DNDEBUG -Id:\python\python27\include -Id:\python\python27\PC /Tcsrc/liblo.c /Fob
    uild\temp.win32-2.7\Release\src/liblo.obj -ID:\tmp\liblo-0.26
    liblo.c
    D:\tmp\liblo-0.26\lo/lo_endian.h(34) : fatal error C1083: Cannot open include fi
    le: 'netinet/in.h': No such file or directory
    error: command '"D:\apps\Microsoft Visual Studio 10.0\VC\BIN\cl.exe"' failed wit
    h exit status 2
    
  • Now that's interesting. It's looking for netinet/in.h which is a POSIX (ie. unix / linux type) thing. Not surprising it didn't find it on a Windows system. Why is it looking for it? Let's open up D:\tmp\liblo-0.26\lo/lo_endian.h(34) from the error message and see what's going on
    #ifdef WIN32
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #else
    #include <netinet/in.h>
    #endif
    
    So it's basically saying if it's a Windows machine use winsock2, otherwise use netinet. This makes sense, but doesn't appear to be working. For some reason WIN32 isn't being defined - let's define it ourselves with some more extra_compile_args:
            extra_compile_args = ['-ID:\\tmp\\liblo-0.26', '-ID:\\tmp\\Pre-built.2\\include', '-DWIN32'],
    
    
  • Let's try now
    D:\tmp\pyliblo-0.9.1>python setup.py build
    running build
    running build_ext
    building 'liblo' extension
    D:\apps\Microsoft Visual Studio 10.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS- /
    DNDEBUG -Id:\python\python27\include -Id:\python\python27\PC /Tcsrc/liblo.c /Fob
    uild\temp.win32-2.7\Release\src/liblo.obj -ID:\tmp\liblo-0.26 -DWIN32 -ID:\tmp\P
    re-built.2\include
    liblo.c
    src/liblo.c(7477) : warning C4244: 'function' : conversion from 'double' to 'flo
    at', possible loss of data
    src/liblo.c(8002) : warning C4244: 'function' : conversion from 'double' to 'flo
    at', possible loss of data
    creating build\lib.win32-2.7
    D:\apps\Microsoft Visual Studio 10.0\VC\BIN\link.exe /DLL /nologo /INCREMENTAL:N
    O /LIBPATH:d:\python\python27\libs /LIBPATH:d:\python\python27\PCbuild lo.lib /E
    XPORT:initliblo build\temp.win32-2.7\Release\src/liblo.obj /OUT:build\lib.win32-
    2.7\liblo.pyd /IMPLIB:build\temp.win32-2.7\Release\src\liblo.lib /MANIFESTFILE:b
    uild\temp.win32-2.7\Release\src\liblo.pyd.manifest
    LINK : fatal error LNK1181: cannot open input file 'lo.lib'
    error: command '"D:\apps\Microsoft Visual Studio 10.0\VC\BIN\link.exe"' failed w
    ith exit status 1181
    
  • So it's compiled now, but fails to link. It wants to link against lo.lib but it can't find it. There's two reasons for that - firstly it doesn't know where to look. We'll add some extra_link_args to show it where our .lib file is. Secondly, it's got the wrong filename - *nix systems will append "lib" to the front of library names, so we'll have to do that manually here and change the libraries option from 'lo' to 'liblo'
    ext_modules = [
        Extension(
            'liblo',
            [use_cython and 'src/liblo.pyx' or 'src/liblo.c'],
            extra_compile_args = ['-ID:\\tmp\\liblo-0.26', '-DWIN32', '-ID:\\tmp\\Pre-built.2\\include'],
     extra_link_args = ['/LIBPATH:D:\\tmp\\liblo-0.26\\lib\\ReleaseDLL',
            libraries = ['liblo']
        )
    ]
    
  • Surely this time ...
    D:\tmp\pyliblo-0.9.1>python setup.py build
    running build
    running build_ext
    building 'liblo' extension
    D:\apps\Microsoft Visual Studio 10.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS- /
    DNDEBUG -Id:\python\python27\include -Id:\python\python27\PC /Tcsrc/liblo.c /Fob
    uild\temp.win32-2.7\Release\src/liblo.obj -ID:\tmp\liblo-0.26 -DWIN32 -ID:\tmp\P
    re-built.2\include
    liblo.c
    src/liblo.c(7477) : warning C4244: 'function' : conversion from 'double' to 'flo
    at', possible loss of data
    src/liblo.c(8002) : warning C4244: 'function' : conversion from 'double' to 'flo
    at', possible loss of data
    D:\apps\Microsoft Visual Studio 10.0\VC\BIN\link.exe /DLL /nologo /INCREMENTAL:N
    O /LIBPATH:d:\python\python27\libs /LIBPATH:d:\python\python27\PCbuild liblo.lib
     /EXPORT:initliblo build\temp.win32-2.7\Release\src/liblo.obj /OUT:build\lib.win
    32-2.7\liblo.pyd /IMPLIB:build\temp.win32-2.7\Release\src\liblo.lib /MANIFESTFIL
    E:build\temp.win32-2.7\Release\src\liblo.pyd.manifest /LIBPATH:D:\tmp\liblo-0.26
    \lib\ReleaseDLL
       Creating library build\temp.win32-2.7\Release\src\liblo.lib and object build\
    temp.win32-2.7\Release\src\liblo.exp
    C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\mt.exe -nologo -manifest build
    \temp.win32-2.7\Release\src\liblo.pyd.manifest -outputresource:build\lib.win32-2
    .7\liblo.pyd;2
    
    build\temp.win32-2.7\Release\src\liblo.pyd.manifest : general error c1010070: Fa
    iled to load and parse the manifest. The system cannot find the file specified.
    error: command 'mt.exe' failed with exit status 31
    
  • Now it's complaining that it can't find the manifest file that should have been created in the linking stage. We'll need to explicitly tell the linker to generate the manifest:
    ext_modules = [
        Extension(
            'liblo',
            [use_cython and 'src/liblo.pyx' or 'src/liblo.c'],
            extra_compile_args = ['-ID:\\tmp\\liblo-0.26', '-DWIN32', '-ID:\\tmp\\Pre-built.2\\include'],
     extra_link_args = ['/LIBPATH:D:\\tmp\\liblo-0.26\\lib\\ReleaseDLL', '/MANIFEST'],
            libraries = ['liblo']
        )
    ]
    
  • And ...
    D:\tmp\pyliblo-0.9.1>python setup.py build
    running build
    running build_ext
    building 'liblo' extension
    D:\apps\Microsoft Visual Studio 10.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS- /
    DNDEBUG -Id:\python\python27\include -Id:\python\python27\PC /Tcsrc/liblo.c /Fob
    uild\temp.win32-2.7\Release\src/liblo.obj -ID:\tmp\liblo-0.26 -DWIN32 -ID:\tmp\P
    re-built.2\include
    liblo.c
    src/liblo.c(7477) : warning C4244: 'function' : conversion from 'double' to 'flo
    at', possible loss of data
    src/liblo.c(8002) : warning C4244: 'function' : conversion from 'double' to 'flo
    at', possible loss of data
    creating build\lib.win32-2.7
    D:\apps\Microsoft Visual Studio 10.0\VC\BIN\link.exe /DLL /nologo /INCREMENTAL:N
    O /LIBPATH:d:\python\python27\libs /LIBPATH:d:\python\python27\PCbuild liblo.lib
     /EXPORT:initliblo build\temp.win32-2.7\Release\src/liblo.obj /OUT:build\lib.win
    32-2.7\liblo.pyd /IMPLIB:build\temp.win32-2.7\Release\src\liblo.lib /MANIFESTFIL
    E:build\temp.win32-2.7\Release\src\liblo.pyd.manifest /LIBPATH:D:\tmp\liblo-0.26
    \lib\ReleaseDLL /MANIFEST
       Creating library build\temp.win32-2.7\Release\src\liblo.lib and object build\
    temp.win32-2.7\Release\src\liblo.exp
    C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\mt.exe -nologo -manifest build
    \temp.win32-2.7\Release\src\liblo.pyd.manifest -outputresource:build\lib.win32-2
    .7\liblo.pyd;2
    running build_scripts
    creating build\scripts-2.7
    copying and adjusting scripts\send_osc.py -> build\scripts-2.7
    copying and adjusting scripts\dump_osc.py -> build\scripts-2.7
    renaming build\scripts-2.7\send_osc.py -> build\scripts-2.7\send_osc
    renaming build\scripts-2.7\dump_osc.py -> build\scripts-2.7\dump_osc
    
  • Yay, it built! (About bloody time ...)

Use it!

Now we're ready to check that pyliblo works and get to using it. Make a new scratch directory and copy D:\tmp\pyliblo-0.9.1\build\lib.win32-2.7\liblo.pyd, D:\tmp\liblo-0.26\lib\ReleaseDLL\liblo.dll and D:\tmp\Pre-built.2\dll\x86\pthreadVC2.dll into it. Run python from that directory and try to import liblo:
D:\tmp\test>python
Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> import liblo
>>> dir(liblo)
['Address', 'AddressError', 'Bundle', 'Message', 'Server', 'ServerError', 'Serve
rThread', 'TCP', 'UDP', 'UNIX', '_Blob', '_ServerBase', '__builtins__', '__doc__
', '__file__', '__name__', '__package__', '__test__', '__version__', '_inspect',
 '_weakref', '_weakref_method', 'make_method', 'send', 'struct', 'time']
>>>
We're away!

Friday, 22 June 2012

Another stove run

Fired up the stove again a couple of nights ago. Made some tasty, tasty jaffles on it. Mmmm, jaffles.

It took quite some time to melt the cheese, so it's not putting out a great amount of heat. However the main point of this run was to see what happens when the stove is left alone after the burn - in the previous burn I put the char into a sealed container to prevent it from burning. Turns out the char does keep burning as I expected - the next day there was just a tiny bit of char and ash left in the stove.

So I need some way of stopping the combustion ... I guess either cooling it down, or stopping the oxygen getting in. I prefer to not to quench it if possible (makes a bit of a mess), so maybe a sealed lid and some sort of ring to block the holes in the outer tin?

Sunday, 17 June 2012

EverythingNice stove Mk II

So the initial burn of my EverythingNice stove went pretty well but it can still be improved. The main issue with it was the "cone" of uncharred fuel left in the bottom after the burn. From my (admittedly not perfect) understanding of TLODs1, this shape makes sense due to the direction of flow of the hot gasses in the inner chamber.

My simple solution (I don't claim to have come up with the idea, others have done this before me) was to insert a cone-shaped piece of metal into the bottom to prevent any fuel from sitting where it wouldn't be burnt. The cone was made from the bottom of a tin of tomatoes (approx same diameter as the outer tin).

Circular piece of metal cut along a radius, and two holes drilled near the cut

The cone shape formed and secured with a bolt

The edges were snipped a bit so I could bend it to fit nicely inside the tin, and then it was simply placed at the bottom. I didn't really feel like watching it for an hour this time so I only filled it up maybe just over 1/2 way with 100g of pellets for the burn. I lit it the same way as before, soaking a couple of pellets in alcohol for a couple of minutes, putting them on top and lighting them.

Also played around with putting cans on top to try to increase the draw. Seemed to give a slightly stronger flame, but not much.
The results:
  • Seemed to take a little longer to achieve a nice consistent flame cap. Not sure if this was the cone in the bottom, or because I only filled it halfway up. (What's that about only changing one variable at a time?)
  • Once it was going, had a nice steady flame as before.
  • The 100g of fuel burnt for ~32mins and produced 19g of nice biochar. (Okay, I couldn't resist throwing a couple of seeds and leaves in there to see what would happen, so I guess slightly over 100g of fuel)
  • When the flame died down and went out, it smoked a little for maybe 5-10 seconds, but that was it.
  • After it had stopped smoking I looked into the chamber and noticed that a little of the char was glowing red. Taking this as a sign that the charcoal was now combusting (which I didn't want, I wanted to keep it), I poured it out into a metal tin and put the lid on to deprive it of oxygen.
  • After it had cooled down, the char left behind was much nicer than before. All fully pyrolised.

All fuel fully pyrolised. Yay!
So, in the end, very happy with Mk II of my EverythingNice stove at the moment. I'll do some water boil tests to get some idea of the heat output in the near future.

[1] : TLOD (Top-Lit Opposing Draft), the mechanism by which the EverythingNice and Lucia stoves (invented by Nat Mulcahy of Worldstove) operate. A lot of people out there claim that they are TLUDs, but they are a different beast altogether. I'll post about the differences and the airflow in TLODs in a future post.

Saturday, 16 June 2012

EverythingNice stove build

I've been playing with home made gasifier stoves for a little while now. I'd watch some youtube videos of other people's stoves, find some tin cans, drill some holes and fill it with some biomass that was lying around. The results were never great, they would usually burn for a little while and then go out and give out lots of smoke. Using different quality fuel each time also made it really hard to tell how changes I had made to the stoves affected them.

So I decided to get some proper fuel and make a proper version of the EverythingNice stove from Worldstove (plans are here).

First thing was to find some suitable tins. I needed the two diameters to be within 8-10mm of each other, and the smaller tin to be 8-10mm shorter. After exploring the aisles of the local supermarket for some time, I ended up with a tin of Lindt drinking chocolate (with a nice lid) and a standard baked-beans can. Following the instructions I drilled a series of 12mm holes around the base of the Lindt tin, and then cut a 37mm hole out of the centre of the lid with tinsnips :

Lindt chocolate tin
The inner tin got as many 4mm holes as I could, centred on a line 18mm from the bottom of the tin.
Old baked beans can
 Each tin had a 3mm hole drilled in the bottom at the centre, so a M3 bolt could be used to keep the two tins centred.
Holes drilled for centring tins

Centred using one M3 bolt
Turns out finding wood pellets in Sydney isn't as easy as I thought. There are places that sell them, but they seem to want to sell by the pallet load. I found this product called Oz-Pet Cat & Pet Litter which are just wood pellets, but sold as kitty litter. Got a 10kg bag for ~ $14 from a local pet store.

Fuel pellets masquerading as kitty litter
Now for the fun part. I filled the inner tin up to the "fill line" (18mm from the top) with pellets. I soaked a couple of wood pellets in some metho for about 5 mins. Then I dropped them on top and lit them using my girlfriend's creme brulee torch (sshhh).

Here's what happened:
  • Stove lit nicely with a blue flame (due to the alcohol). Began gasifying within around 2 mins
  • Burned with a fairly strong orange flame for ~55mins
  • Produced virtually no smoke (until the end ...)
  • After around 55mins, the flame died down and a little smoke started to be produced
  • After the flame went out, it made lots and lots of smoke. I mean lots. I assume this would have gone on for a while, but I poured a bucket of water over it. That stopped it smoking.
In this photo you can see the flame ...

... and in this one you can see the tin. Use your imagination to combine the two.
 After everything had cooled down a bit I had a look at what was left of the wood pellets. On top they were very nicely pyrolised, but as I dug further down it turned out there was a cone-shaped region of unburnt pellets at the bottom. This would have been what was causing all the smoke at the end. Here's what was left:
The aftermath.
Note that the unburnt pellets have swollen up quite a bit from the water, they would have been the same size as the charred ones.

So, all in all, I was quite happy with the stove, especially for a first (proper) attempt. It burnt really well while it was alight, just need to get it to char all the fuel, and to not smoke so much once it's done.