Read a Book by Remote Control

Array of LED modulesThe center-mounted ceiling fixture found in most homes is a lighting fixture whose best use is perhaps to provide enough light to install other lights. You are virtually guaranteed to cast a shadow on whatever task you undertake, or have the light source in your field of vision, or in some cases, both.

That's the case in my small apartment where the single futon that I use for reading and watching television sits against the wall, facing in. During the day, the window behind it lets plenty of sunlight in, but at night, the only light source is that ubiquitous ceiling fixture which, by virtue of being behind the book I'm reading (rather than behind me), doesn't do much to differentiate the type from the paper.

Of course the solution is to put a lamp beside the futon. But this isn't that kind of apartment. A lamp would take up precious floor space, and I'm using the floor for other things like standing and walking. I do have wall space though.

In fact, the ideal lamp for my situation would not take up any space, so that one isn't even aware of it if when off. It should be energy efficient, but not an ugly, toxic fluorescent lamp. A string of LEDs perched on the window frame would be just about right.

There are two lighting goals for this project. The first is to provide back fill light for reading a book. Most of the light in the room would still come from the ceiling fixture, but the LEDS will bounce extra light on the ceiling behind the reader and illuminate the page. The second goal is to have house lights for watching TV and movies. Lights that can be controlled by remote, so that after watching a movie in the dark, I don't have to stumble across the room to turn on the lights. The LEDs alone achieve the first goal. The second needs some computer automation.

A single LED module

The easiest way to control the LEDs and provide a nice dimming function to ease transitions in and out of black is to do pulse width modulation (PWM) which is electronic-speak for turning something on and off real fast. You could do this with just a parallel port on a computer, but it makes more sense to have a programmable controller like the one on an Arduino handle a task like that.

To construct the system, I bought 20 white LED modules from SparkFun, and strung them together in two channels of 10 modules each. The mounting brackets they provide (I broke off the screw attachment and just used the double sided tape) have enough room to thread the jumper cable for the second channel through the brackets for the first. With this method, alternating modules are on channels in an odd/even configuration. This is helpful in the low end of the dimming range where the ability to have the different channels at separate levels gives the appearance of smoother dimming.Graph of output functions

The Arduino is very simple to use. It has a Java based IDE so that you can instantly upload your programs to the controller and test them out. I wrote a program that receives input over the USB connection and sets PWM values appropriate for the desired light level. Setting the values linearly didn't produce a fade that felt linear, so I applied a simple exponential function to adjust the output to appear more linear. I used different functions for each channel so that in the lower part of the fade, the channels have values with different luminosity to smooth the lower end, but as they increase in value, they approach 1 and the output values are not much different in luminosity.

  • int(255*pow(x/255.0, 2.0))
  • int(255*pow(x/255.0, 1.6))

The next component is the software that controls the system. It listens for IR events from an IguanaWorks USB IR tranceiver via LIRC and fades the lights appropriately. It responds to direct on/off commands, but it also watches for commands sent to other systems to infer what is going on in the room. For instance, if it sees the TV turn on, it fades the lights up, then slowly to half. After seeing further IR activity, it fades the lights out on the assumption that everyone has found their seat. When the TV turns off, the lights come back up.

I could hook up a physical button or switch to the Arduino to control the lights as well, but since my remote is programmable, why add more clutter? I have a Harmony 880 universal remote, which is activity based. To use it, one begins by pressing a button for an activity such as "Watch a DVD" or "Watch TV". I added a new activity, which may be unusual for a remote control: "Read a book".

 Remote control

0 comments

mtstat 0.7.3

mtstat is now totally on launchpad. You can evendownload files.

I moved a few things around for 0.7.3. The MySQL plugins are now in mysql.mtstat instead of mtstat_mysql. (To go along with my putting the NDB/Connectors Python stuff in mysql.cluster - I'm trying to make a mysql namespace here) And I split up the mysqlqps plugin into mysqlqps, mysqlhandler and mysqlqcache. You can do multiple plugins like:


mtstat -Mmysqlqps,mysqlhandler


And you'll get output like:



_uptime __sel__ __ins__ __del__ __upd__ _quest_|___hf__ __hnxt_ __hkey_ __rrnd_ __rnxt_


 1998k      0       0       0       0       0 |     0       0       0       0       0 


  1998k     80       8       0       5     411 |     0     359     364       5   10144 


  1998k     27       8       0       6     288 |     0     240     222       1       2 


  1998k     86       7       0       8     531 |     0     300     411       3   10141 


  1998k     29       4       0       2     388 |     0      77     107       0    5062 


  1998k     35       1       0       2     193 |     0      24     117       1       3 


  1998k    100       4       0       4     704 |     0      95     356       1     665 


  1998k    110       7       0      24    1083 |     0     127     416       4    9470 




Yoshinori pointed out a bug in the MySQLdb adapter. In the C code it passes a default port value of 3306. Of course, this means that if you don't set the port in code but expect to pick up the port number from my.cnf, it won't work. The patch is really, really small. The port number passed to mysql_real_connect() should be 0 - not 3306. But it might be a while before that hits. So for now, if you need to do an alternate port, you can either get a copy of MySQLdb and apply this patch:


--- _mysql_connections.c.orig 2007-08-03 23:20:28.000000000 -0700
+++ _mysql_connections.c 2007-08-03 23:20:33.000000000 -0700
@@ -15,7 +15,7 @@
#endif
char *host = NULL, *user = NULL, *passwd = NULL,
*db = NULL, *unix_socket = NULL;
- uint port = 3306;
+ uint port = 0;
uint client_flag = 0;
static char *kwlist[] = { "host", "user", "passwd", "db", "port",
"unix_socket", "conv",


Or you can hard code your port into mysql.mtstat.mysqlbase.

Also, I've turned on the bug tracker on launchpad, so please let me know if you're having any problems.
0 comments
Tags: code db python

Updates to NDB/Connectors

The NDB/Connectors have added support for Ruby, as well as Asynchronous Transaction support for Java, Python and Perl.

The Ruby support, of course, means that new you can interact with your MySQL Cluster installation using the NDBAPI from all your Ruby code.

The async stuff is especially cool, because it means you can send transactions to the Cluster and get responses by way of callbacks defined in the connector language. So you can do something like this:

class testaclass(object):

def __init__(self, recAttr):
self.recAttr=recAttr

def __call__(self, ret, myTrans):
print "value = ", self.recAttr.get_value()

#snip

myTrans = myNdb.startTransaction()

myOper = myTrans.getNdbOperation("mytablename")
myOper.readTuple(ndbapi.NdbOperation.LM_Read)

myOper.equal("ATTR1", 245755 )

myRecAttr= myOper.getValue("ATTR2")

a = testaclass(myRecAttr)

myTrans.executeAsynchPrepare( ndb.Commit, a )

myNdb.sendPollNdb(3000,1)

May not seem as exciting with just a single operation - but you can toss tons of them down there and then poll for the results.

We've also added support for exceptions in the Connector language. So instead of checking if return values are null or -1, the wrapper code will throw a Java or Perl or Python exception.

There is a also a new mailing list at lists.mysql.com for discussion of the development of the NDB/Connectors. Come join us and have some fun!
0 comments

NDB/Connectors for MySQL Cluster on Launchpad

I've been given the go ahead to release my NDB/Connectors code. These connectors wrap the NdbApi for a variety of languages, including Python, Perl, Java and C# at the moment. I'm managing development using Launchpad, so go to

https://launchpad.net/ndb-connectors

To get the latest version or status of the code. If you would like to contribute, feel free to branch a copy of the source using bzr and send me a revision bundle. There is also an ndb-connectors team on launchpad you can join if you'd like to participate more directly in the development. For either of these options to work, you need to first sign the MySQL Code Contributor License Agreement to assign copyright of your contributions to MySQL, Inc.

I hope to have a mailing list set up soon for discussion.
0 comments

NDB/Connectors 0.1

So I've expanded the scope of the NDB/Python wrappers I was working on. Now I've got Python, Perl and C# wrappers working, at least for basic functionality. I've setup a trac instance and put a roadmap and all of that type of stuff up. If you are interested in hacking, let me know and we can talk about subversion access and all that.

For the moment, I've turned off code downloading. I'll post again when I've enabled it again.
0 comments
Tags: db perl python code