Xbox Live Camera on Linux (Part 5)

A brief gap in the clouds this evening gave me a window of about five minutes to test out a couple of Xbox cameras under a night-time sky. I took 30 frames of five seconds each, ten seconds apart. Here are the first and last frames from a camera that I’ve modded by removing the IR filter and killing the on-board LEDs. At the time I had the standard lens fitted.

It’s not visible at reduced resolution, but click on the images and there are most definitely a number of stars from Ursa Major showing up there. What is also sadly painfully obvious is the amount of sensor noise.

This is the first of a similar run from a camera with the LEDs killed, but with the IR filter still in place:

It may be partly down to the cloud cover, but the stars are nowhere near as obvious. I shall retry the test later in the week when we have clear skies forecast.

What was also interesting was that I’d left the front of the case off the second camera and the noise level was significantly lower. I’m going to have to try that with the IR cam to see if it makes as large a difference. Remounting the camera in a different housing and fitting a fan may well make sense.

Posted in Astroimaging, Astronomy, Computing, Linux | Leave a comment

Xbox Live Camera on Linux (Part 4)

The promised instructions on rebuilding the kernel UVC kernel module. Here’s what I did on my Ubuntu 11.10 Aspire 1. If you substitute in your own kernel version number then you should be ok if you’re running other releases. I may experiment with something RedHat-ish later to find out how to do it there. Because I’m lazy, and because I’ve spent many years working as a sysadmin, I do this all whilst logged in as root. I’ve reconstructed the sequence of commands from my shell history, so it should be correct, but let me know if you have problems.

# apt-get install linux-source-3.0.0 kernel-package linux-headers-`uname -r`
# cd /usr/src
# tar jxvf linux-source-3.0.0.tar.bz2
# cd linux-source-3.0.0
# ln -s /boot/config-`uname -r` .config
# ln -s /usr/src/linux-headers-`uname -r`/Module.symvers .

At this point you can patch the UVC driver, and assuming that went well, continue:

# make modules_prepare
# make M=drivers/media/video/uvc

And you should now have a re-built driver. To load it manually you can just do:

# insmod drivers/media/video/uvc/uvcvideo.ko ctrltimeout=10000 timeout=10000

But to get it loaded into the kernel automagically a little more work is required:

# mkdir -p /lib/modules/`uname -r`/updates
# cp drivers/media/video/uvc/uvcvideo.ko /lib/modules/`uname -r`/updates
# depmod -a
# echo "options uvcvideo ctrltimeout=10000 timeout=10000" > /etc/modprobe.d/uvcvideo.conf

The patched module should now be loaded when your camera is hooked up. To check that the settings have been changed you can see their current values using:

$ cat /sys/module/uvcvideo/parameters/ctrltimeout
$ cat /sys/module/uvcvideo/parameters/timeout

Or if you want to reload the module manually:

# modprobe -r uvcvideo
# modprobe -v uvcvideo

Posted in Astroimaging, Astronomy, Computing, Linux | 1 Comment

Xbox Live Camera on Linux (Part 3)

It seems I made an error in my initial attempt to get the exposure settings working for this camera in the uvcvideo driver. The camera appears to accept a far greater range of settings for exposure than I initially thought. After tinkering the with exposure settings for some time it seems to be the case that for values up to 25,000 the exposure setting actually represents the exposure time in units of 100μsec. Beyond that things get a bit non-linear. Whilst 25,000 looks to give an exposure time of 2.5 seconds, 25,001 suddenly jumps up to about 3.3 seconds, and by the time the setting has reached 35,000 then the exposure time is about 5 seconds. It does not appear to be able to increase the exposure time beyond five seconds, but initially that looks pretty good for a night-time sky camera.

So, my previous UVC driver patch needs modifying. Here’s the entire thing again. This time I’ve set the maximum exposure time to 50000 which seems a reasonable choice given that I can’t get exposures longer than five seconds. I’ve found it’s best to load this with the ctrltimeout and timeout parameters set to 10000. Lower values work for me for 640×480 resolution frames, but when I bumped the resolution up higher then I started getting timeouts again. Once again, be wary of whitespace changes.


--- drivers/media/video/uvc/uvc_ctrl.c~  2012-04-13 22:37:19.278971810 +0100
+++ drivers/media/video/uvc/uvc_ctrl.c  2012-04-18 13:46:46.916464906 +0100
@@ -963,9 +963,17 @@
     v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN,
              uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
 
-  if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX)
+  if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) {
     v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX,
              uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
+    if ( v4l2_ctrl->id == V4L2_CID_EXPOSURE_ABSOLUTE &&
+        v4l2_ctrl->maximum == -1 &&
+        chain->dev->quirks &
+        UVC_QUIRK_XBOX_EXPOSURE_FIX ) {
+      uvc_trace(UVC_TRACE_CONTROL, "Xbox queryctl max exp. set to 50000.");
+      v4l2_ctrl->maximum = 50000;
+    }
+        }
 
   if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)
     v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES,
@@ -1202,6 +1210,12 @@
            uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
     max = mapping->get(mapping, UVC_GET_MAX,
            uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
+    if ( max == -1 && xctrl->id == V4L2_CID_EXPOSURE_ABSOLUTE &&
+        chain->dev->quirks &
+        UVC_QUIRK_XBOX_EXPOSURE_FIX ) {
+      uvc_trace(UVC_TRACE_CONTROL, "Xbox max exposure set to 50000.");
+      max = 50000;
+    }
     step = mapping->get(mapping, UVC_GET_RES,
             uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
     if (step == 0)
--- drivers/media/video/uvc/uvc_driver.c~  2012-04-15 15:36:27.858728125 +0100
+++ drivers/media/video/uvc/uvc_driver.c  2012-04-13 22:29:55.556771975 +0100
@@ -47,6 +47,7 @@
 static unsigned int uvc_quirks_param = -1;
 unsigned int uvc_trace_param;
 unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
+unsigned int uvc_ctrl_timeout_param = UVC_CTRL_CONTROL_TIMEOUT;
 
 /* ------------------------------------------------------------------------
  * Video formats
@@ -2016,6 +2017,8 @@
 MODULE_PARM_DESC(trace, "Trace level bitmask");
 module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(timeout, "Streaming control requests timeout");
+module_param_named(ctrltimeout, uvc_ctrl_timeout_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ctrltimeout, "Control control requests timeout");
 
 /* ------------------------------------------------------------------------
  * Driver initialization and cleanup
@@ -2351,6 +2354,15 @@
     .bInterfaceProtocol  = 0,
     .driver_info    = UVC_QUIRK_PROBE_MINMAX
         | UVC_QUIRK_IGNORE_SELECTOR_UNIT },
+        /* Microsoft XBox Live USB Web Camera */
+        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                                | USB_DEVICE_ID_MATCH_INT_INFO,
+          .idVendor             = 0x045e,
+          .idProduct            = 0x0294,
+          .bInterfaceClass      = USB_CLASS_VIDEO,
+          .bInterfaceSubClass   = 1,
+          .bInterfaceProtocol   = 0,
+          .driver_info          = UVC_QUIRK_XBOX_EXPOSURE_FIX },
   /* Generic USB Video Class */
   { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
   {}
--- drivers/media/video/uvc/uvc_video.c~  2012-04-13 22:31:47.037324898 +0100
+++ drivers/media/video/uvc/uvc_video.c  2012-04-13 22:31:04.009110557 +0100
@@ -75,7 +75,7 @@
   int ret;
 
   ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size,
-        UVC_CTRL_CONTROL_TIMEOUT);
+        uvc_ctrl_timeout_param);
   if (ret != size) {
     uvc_printk(KERN_ERR, "Failed to query (%s) UVC control %u on "
       "unit %u: %d (exp. %u).\n", uvc_query_name(query), cs,
--- drivers/media/video/uvc/uvcvideo.h~  2012-04-13 22:27:33.248066424 +0100
+++ drivers/media/video/uvc/uvcvideo.h  2012-04-13 22:39:23.599589380 +0100
@@ -212,6 +212,7 @@
 #define UVC_QUIRK_FIX_BANDWIDTH    0x00000080
 #define UVC_QUIRK_PROBE_DEF    0x00000100
 #define UVC_QUIRK_RESTRICT_FRAME_RATE  0x00000200
+#define UVC_QUIRK_XBOX_EXPOSURE_FIX  0x00000400
 
 /* Format flags */
 #define UVC_FMT_FLAG_COMPRESSED    0x00000001
@@ -575,6 +576,7 @@
 extern unsigned int uvc_no_drop_param;
 extern unsigned int uvc_trace_param;
 extern unsigned int uvc_timeout_param;
+extern unsigned int uvc_ctrl_timeout_param;
 
 #define uvc_trace(flag, msg...) \

Posted in Astroimaging, Astronomy, Computing, Linux | Leave a comment

Xbox Live Camera on Linux (Part 2)

Last night I discovered that I wasn’t able to change the gain setting on the camera using the V4L2 API. No matter what setting I used all my captures turned out the same, using what I presume to be the default gain of setting of zero.

I know the gain settings can be changed under Windows, but I couldn’t see what I might be doing that was wrong and was on the point of abandoning the idea of using the camera when it occurred to me that perhaps the gain setting can only be altered after streaming from the camera has been started. This isn’t the case with exposure, which can be set before streaming starts. So as a last resort I re-coded my capture app to set the gain after enabling streaming and amazingly it all started working.

So now I just need to get some testing done under the stars. I’m a little concerned that using the “fish-eye” lens with such a large field of view I may not get enough light from a single star onto one pixel for it to give a clear image, but the only way to find out is to do some testing.

Posted in Astro Equipment, Astronomy, Linux, Projects | Leave a comment

Kernel Patch for Xbox Live Camera on Linux

I’ve done some more work on getting the Xbox Live camera to work properly on Linux this evening and have submitted a patch to the development mailing list. I don’t know if it will get included in some future driver release or be considered unsuitable, but it does at least make all of the problems I have getting the camera to work with the UVC driver and V4L2 go away.

The patch is below. It’s against the v3.0.0-generic kernel which as of the time of writing is the latest available for Ubuntu 11.10. It may well apply cleanly to the driver sources in both earlier and later kernel releases, but as yet I’ve not tried.

If you wish to use the patch you’ll need to be comfortable patching the kernel and rebuilding the UVC module. I’ll try to write up some details on that later. The module should work normally for all other cameras, but if you’re using the Xbox Live camera then you’ll need to use the ctrltimeout option to increase the timeout from the default. I found that increasing it to 1000 was insufficient, but that 2000 worked fine, so for the purposes of testing I’m doing something like:

insmod uvcvideo.ko ctrltimeout=2000

The patch also forces the reported maximum exposure setting for the camera to 255 if it would otherwise be set to -1. It’s clearly wrong that the minimum is reported as 1, the maximum as -1 and the default as 166, so I suspect this is a firmware issue in the camera and as such I’ve not made the correction optional.

And here’s the patch (whitespace may have been broken, so take care when applying it):

--- drivers/media/video/uvc/uvc_ctrl.c~  2012-04-13 22:37:19.278971810 +0100
+++ drivers/media/video/uvc/uvc_ctrl.c  2012-04-13 23:22:39.840119482 +0100
@@ -963,9 +963,17 @@
     v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN,
              uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
 
-  if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX)
+  if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) {
     v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX,
              uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
+    if ( v4l2_ctrl->id == V4L2_CID_EXPOSURE_ABSOLUTE &&
+        v4l2_ctrl->maximum == -1 &&
+        chain->dev->quirks &
+        UVC_QUIRK_XBOX_EXPOSURE_FIX ) {
+      uvc_trace(UVC_TRACE_CONTROL, "Xbox queryctl max exp. set to 255.");
+      v4l2_ctrl->maximum = 255;
+    }
+        }
 
   if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)
     v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES,
@@ -1202,6 +1210,12 @@
            uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
     max = mapping->get(mapping, UVC_GET_MAX,
            uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
+    if ( max == -1 && xctrl->id == V4L2_CID_EXPOSURE_ABSOLUTE &&
+        chain->dev->quirks &
+        UVC_QUIRK_XBOX_EXPOSURE_FIX ) {
+      uvc_trace(UVC_TRACE_CONTROL, "Xbox max exposure set to 255.");
+      max = 255;
+    }
     step = mapping->get(mapping, UVC_GET_RES,
             uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
     if (step == 0)
--- drivers/media/video/uvc/uvc_driver.c~  2012-04-15 15:36:27.858728125 +0100
+++ drivers/media/video/uvc/uvc_driver.c  2012-04-13 22:29:55.556771975 +0100
@@ -47,6 +47,7 @@
 static unsigned int uvc_quirks_param = -1;
 unsigned int uvc_trace_param;
 unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
+unsigned int uvc_ctrl_timeout_param = UVC_CTRL_CONTROL_TIMEOUT;
 
 /* ------------------------------------------------------------------------
  * Video formats
@@ -2016,6 +2017,8 @@
 MODULE_PARM_DESC(trace, "Trace level bitmask");
 module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(timeout, "Streaming control requests timeout");
+module_param_named(ctrltimeout, uvc_ctrl_timeout_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ctrltimeout, "Control control requests timeout");
 
 /* ------------------------------------------------------------------------
  * Driver initialization and cleanup
@@ -2351,6 +2354,15 @@
     .bInterfaceProtocol  = 0,
     .driver_info    = UVC_QUIRK_PROBE_MINMAX
         | UVC_QUIRK_IGNORE_SELECTOR_UNIT },
+        /* Microsoft XBox Live USB Web Camera */
+        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                                | USB_DEVICE_ID_MATCH_INT_INFO,
+          .idVendor             = 0x045e,
+          .idProduct            = 0x0294,
+          .bInterfaceClass      = USB_CLASS_VIDEO,
+          .bInterfaceSubClass   = 1,
+          .bInterfaceProtocol   = 0,
+          .driver_info          = UVC_QUIRK_XBOX_EXPOSURE_FIX },
   /* Generic USB Video Class */
   { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
   {}
--- drivers/media/video/uvc/uvc_video.c~  2012-04-13 22:31:47.037324898 +0100
+++ drivers/media/video/uvc/uvc_video.c  2012-04-13 22:31:04.009110557 +0100
@@ -75,7 +75,7 @@
   int ret;
 
   ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size,
-        UVC_CTRL_CONTROL_TIMEOUT);
+        uvc_ctrl_timeout_param);
   if (ret != size) {
     uvc_printk(KERN_ERR, "Failed to query (%s) UVC control %u on "
       "unit %u: %d (exp. %u).\n", uvc_query_name(query), cs,
--- drivers/media/video/uvc/uvcvideo.h~  2012-04-13 22:27:33.248066424 +0100
+++ drivers/media/video/uvc/uvcvideo.h  2012-04-13 22:39:23.599589380 +0100
@@ -212,6 +212,7 @@
 #define UVC_QUIRK_FIX_BANDWIDTH    0x00000080
 #define UVC_QUIRK_PROBE_DEF    0x00000100
 #define UVC_QUIRK_RESTRICT_FRAME_RATE  0x00000200
+#define UVC_QUIRK_XBOX_EXPOSURE_FIX  0x00000400
 
 /* Format flags */
 #define UVC_FMT_FLAG_COMPRESSED    0x00000001
@@ -575,6 +576,7 @@
 extern unsigned int uvc_no_drop_param;
 extern unsigned int uvc_trace_param;
 extern unsigned int uvc_timeout_param;
+extern unsigned int uvc_ctrl_timeout_param;
 
 #define uvc_trace(flag, msg...) \
   do { \

Posted in Computing, Linux | Leave a comment

SPC900 Camera on Linux

Because of the problems I’ve been having with the Xbox Live camera with my SheevaPlug I decided to give one of my SPC900 cameras a try. I don’t really want to use these as I had another purpose in mind, but they do at least seem to work pretty well under Windows. I’ve used one successfully for some time for planetary imaging and others are using them for guiding and DSO imaging with the long exposure mod.

Unfortunately as soon as I plugged it in I realised there was going to be trouble. On the SheevaPlug my capture application failed to report many of the controls. Looking at the PWC driver code it appears that it doesn’t support the V4L2_CTRL_FLAG_NEXT_CTRL flag for the VIDIOC_QUERYCTL ioctl call, so it isn’t possible for an application to enumerate all of the controls.

This appears to be fixed in (at least some of) the 3.0 series kernels, so if you’re running, for example, Ubuntu 11.10 then it should work, but as I can’t stand the Unity and Gnome 3 UIs that we seem to be stuck with on Ubuntu 11.10 I shan’t be using that if I have any other possible choice.

Posted in Astroimaging, Astronomy, Computing, Linux | Leave a comment

Xbox Live Camera on Linux

I’ve been tempted to build a couple of camera projects recently, the first being a camera to capture the images to create an Analemma, which shows the path of the sun through the sky at a fixed time (usually at its highest point) each day over the course of a year, and the second being an all-sky camera.

For both of these ideas I decided it would be handy to have a camera connected up to a SheevaPlug as they’re relatively small and low power. I might have been tempted to go for a Raspberry Pi if I’d been able to get any, but I have the SheevaPlugs lying about unused so they seem like a sensible choice anyhow.

The first stage was to decide on a camera. I know of people using the Xbox Live camera for sky images and planetary imaging, so that looked like it would be worth a try and bought a couple from Ebay for the price of a couple of pints of beer. I also ordered a short focal length wide-angle lens that should fit into the same thread as all of these cameras seem to use (a fine M12 thread, as far as I recall).

As the new lens was coming from China and would take several weeks I got on with modding one of the cameras first, opening it up and pulling the LEDs off the PCB. They seem to have a significant effect on the image even though the sensor is supposed to be sealed from their glare. At the same time I removed the IR filter. Using SharpCap on Windows I managed to pick up a few stars so it looked like there were possibilities for using the camera as an all-sky cam overnight, perhaps picking up images of satellites or meteors and meteorites.

That’s when the trouble started. The Xbox Live camera uses the Linux UVC driver which appears to be fairly mature code-wise, but kept throwing errors with my test code. I’m new to the V4L2 API, so for a fair while I was convinced that my code was the problem, but dredging through the driver source I became convinced that there are a number of issues with this camera.

The first is that the camera auto-exposure mode really isn’t suitable for outdoor use so I need to add code to set that myself. This leads directly to the second problem.

Which is that when the camera is queried to find out if it supports manual exposure setting (it does) the response is that the minimum exposure is 1, the maximum is -1 and the default is 166. Clearly that’s nonsensical. The driver clamps out of range inputs to the minimum or maximum values too, so even if I tried to set the exposure to the default value, it ended up being set to -1.

The third problem is that although commands can be sent to the camera over USB and they apparently complete correctly, it looks like the camera itself takes some time to actually complete processing of that command internally. If commands are sent in quick succession (as happens if you want to set the image resolution and then the exposure length) then the later ones just keep timing out. There is a mechanism to allow one of the timeouts to be changed in the driver when it is loaded, but doubling that didn’t help at all and I’m not convinced it would anyhow.

I posted to the UVC developers list about this yesterday, but there’s been no response as yet. They possibly think I’m an idiot, rambling on about the odd behaviour of this camera anyhow. In the meantime however I’ve bodged my application to add a delay of a couple of seconds after every ioctl command sent to the driver (one second wasn’t enough, two seems fairly reliable). This is a messy fix, but I’m not confident with adding delays inside driver code. It still means there are problems when third party code is linked in to applications though, such as libv4l2. I’ve also added code for a new “quirk” in the driver which forces the maximum exposure time to be set to 255. I had a bundle of fun working on this as it meant upgrading the SheevaPlug I was working on with a new release of the OS, and in fact swapping from Ubuntu (which no longer supports ARM processors, apparently) to Debian. More about that in another post. These changes did however allow my code to run correctly most of the time. I still get a few timeouts in the libv4l2 code, but I’ll work on those later. I’ll also post my driver diffs once I get organised.

On the assumption that I can still pick up enough stars to make it interesting during the night, I still have some other issues to deal with. First is that I really need to be change the exposure lengths depending on how light or dark it is, so I need to think of some mechanism for that. The second is that the night time images appear to be fairly noisy, so some method of noise reduction would be useful. For the moment however I intend to procrastinate and worry about both of these issues later.

Posted in Astroimaging, Astronomy, Computing, Linux, Projects | Leave a comment

The Beginning of a New Dobsonian

I recently had the chance to acquire some bits left over from a damaged Skywatcher 250mm Flextube dobsonian telescope for not very many pennies. As a result I’m now the proud owner of a the mirror and cell, spider (with secondary) and focuser:

My plan is to rebuild a new dobsonian telescope around them. Not sure I want the focuser yet, but as I wasn’t paying huge amounts it seemed to make sense to have it until such time as I can afford a Feathertouch 🙂 Finding a suitable size solid tube seems to be tough, so I think I’m going to go for a fixed truss design, but thus far I haven’t decided whether it will be motorised, be mounted on a wedge or made any other significant design decisions. I quite like the idea of doing something in a vaguely steampunk style, but on the other hand there’s the desire to just get the thing built and into use. I’m quite tempted to make curved vanes for the secondary mirror, as having started out with refractors I’m not keen on diffraction spikes.

Posted in Astro Equipment, Astronomy, Projects | 1 Comment

Veg Plot Progress

Busy times at the moment. This is the veg. plot as it looked at the start of March. It’s a big plot and in previous years has taken a very long time to dig over by hand, so this year I invested in a new (well, new to me) toy for the tractor meaning I could do the whole thing, twice, in a couple of hours one Sunday afternoon.

Since then I’ve been planting madly. First, red onions (Red Baron) and brown onions (Sturon), shallots (Golden Gourmet), garlic (Solent Wight), closely followed by my first outdoor sowing of peas and mangetout (Kelvedon Wonder, Hurst Green Shaft, Sugar Ann and Norli.

In the brassica section I have started off cabbages (Greyhound, Red Jewel, Tundra, Prestige), brussels sprouts (Cascade), purple sprouting broccoli (Red Arrow and Rudolph), cavalo nero and romanesco cauliflower, as well as planting some French Breakfast and Cherry Belle radishes and a mix of lettuces.

The roots bed has several rows of parsnips (Cobham Improved Marrow) and carrots (Autumn King and Amsterdam Forcing), beetroot (Boltardy) and swiss chard (Bright Lights).

Finally, the potato bed is now full of a mix of King Edward, Desiree, Charlotte and International Kidney potatoes. I used to plant Maris Piper instead of Desiree, but found them very susceptible to scab.

In the greenhouse I have tomatoes (Gardeners Delight, Costoluto Fiorentino, San Marzano) doing well, and my February sowings of peppers (Corno di Toro, Cayenne, Japapeno and Bird Eye) are also doing well. I’m also waiting for sweet corn to germinate as well as Okra, cucumber (Marketmore), Pumpkins (Orbit) and probably a few other things I’ve forgotten, as well as a selection of herbs.

The polytunnel is the one thing that’s been slow to get moving this year. Normally the peppers, tomatoes and cucumbers occupy it during the height of summer, but before they go in I have a few crops of lettuce, radish and other salad items. I’ve just not got around to getting it ready quickly enough this year though and the only thing in it at the moment is an early crop of peas. Hopefully this weekend, with the bulk of planting done, I’ll be able to get sorted there.

Posted in Polytunnel, Smallholding, Veg plot | Leave a comment

Focal Ratio and Capture Length for Planetary Imaging

Thus far with my planetary imaging I’ve used capture times and focal ratios just “by the book” without actually understanding how the answers were derived, so I decided it was about time I worked things out for myself. I’ve summarised what I’ve worked out in this article. I should point out that I have no real knowledge of optics other than what was required for O-level Physics in the 1980s, so I’ll grant that there may be errors. Feel free to point them out.

First let’s start with Rayleigh’s formula for angular resolution. Simply put, this tells you how “wide” something needs to appear in the sky for you to be able to resolve it with your telescope. The formula is:

R = λ / d

where R is the angular resolution in radians, λ is the wavelength you’re interested in measured in metres and d is the diameter of the primary lens or mirror (also in metres). If you’re maths-phobic don’t worry about the fact I’m using radians rather than degrees or arc-seconds here. It’ll all come out in the wash later.

The next thing we need to know about is “plate scale”. This isn’t something you get when your dishwasher isn’t functioning correctly, but rather it tells you the relationship between size on the image plane and the field of view. It’s fairly trivial to derive from first principles, just a little basic trigonometry, but for brevity (not my strong suit at the best of times 🙂 I’ll skip that here. It’s given by:

S = 1 / f

where S is angular size in radians per metre of image plane and f is the focal length of the telescope also in metres. We can use this to calculate how much of the field of view is represented by a single pixel on the camera sensor. For example, if we have a telescope with a focal length of 1.2m and an SPC900 camera which has a pixel size of 5.6μm, or 5.6×10-6m, that each pixel represents 5.6×10-6 / 1.2 radians of the field of view, or 4.67×10-6 radians. This is a thoroughly awkward number to work with, so it’s handy that I know there are 206265 arcseconds in a radian and multiplying by that gives us a figure of 0.96 arcseconds per pixel.

When we’re out in the white heat of a planetary imaging session, it would be useful to know that we’re capturing as much detail as we possibly can. Ideally we want to make sure that at least one pixel on the camera sensor is dedicated to the smallest thing our telescope can resolve. If we represent the pixel size in metres by w, we can write this in terms of R and S above:

R = Sw

and expanding the terms:

λ / d = w / f

The appearance of d, the diameter of the primary, and f, the focal length here makes the rearrangement to give the focal ratio just too good an opportunity to miss:

f / d = w / λ

In other words, if we know what our pixel size is and we know what wavelength we’re imaging in, we can calculate the focal ratio we should be using. Picking blue light with a wavelength of 400nm, or 4×10-7m and staying with our SPC900 example with a sensor element size of 5.6×10-6m, that gives us:

focal ratio = 5.6×10-6 / 4×10-7

and doing the calculation that somewhat surprisingly comes out as:

focal ratio = 14

So, to get the best data capture you can all you need to do is bump the focal length up to 14? Is that it? Does Damian Peach need his bumps felt for imaging at a focal ratio of forty-two brazilian? (I almost typed Damian Hirst there. Imagine, if Damian Hirst did astrophotography. You could guarantee that Taurus would never be the same again…)

Well, perhaps not. One reason involves more maths and whilst I understand the results I probably can’t explain it very well so I’ll skip that bit. It’s called Nyquist’s Sampling Theorem and simply put states that if you’re sampling an analogue signal then your sample rate should be at least twice that of the highest signal frequency to accurately recreate the signal. If we allow that the same rules should apply to digital imaging (which is sampling an analogue signal after all) then we really want two pixels per smallest resolvable detail. That would double our pixel size in the above calculation, giving us a desired focal ratio of f/28.

Another reason is that although we’ve used 5.6μm as the pixel size in this instance, that’s actually their width and height. They’re not round though, and are longer on the diagonal by a factor of √2, or about 1.4 (near enough for our purposes). So, perhaps we should increase the pixel size by a factor of 1.4 to allow for this, giving a final desired focal ratio of f/39.2. Since I like round numbers, call it f/40.

If I’d picked a wavelength in the green region, say 560nm, we could have had the numbers come out very simply as f/10, f/20 and f/28, but only because that’s a nice multiple of our pixel size.

What’s interesting about this is that it’s completely independent of your telescope, a result I certainly didn’t expect. Of course there are other factors that will come into play such as the amount of light your scope can get onto the sensor in the first place. With small diameter scopes that’s possibly more likely to be the limiting factor.

Is there any point in going beyond f/40? I don’t know, but it seems unlikely. Beyond that point it seems to me that all you’re likely to be doing is increasing the size of the image without adding more detail and it’s entirely possible that’s easier to do in post-processing, especially given the increased difficulty of keeping the image on the sensor as the focal ratio goes up.

And so to capture times.

For this we’re going to go back to the plate scale calculation and I’m going to stick with our 1.2m focal length SPC900 example where each pixel corresponds to 0.96 arcseconds of the field of view. During the capture run we’d ideally like all the features of the planet to stay in the same place on the camera sensor. Obviously good tracking is necessary for that, but even that won’t help with distortion of the image due to the rotation of the target planet. As the planet rotates its features will move across the image plane and if we don’t stop imaging soon enough they’ll blur into data already recorded for the features “ahead” of them that have already been recorded at that position on the sensor.

We can’t stop it completely, so we just need to make an arbitrary decision about how much movement across the image plane is acceptable. I’m going to suggest half a pixel, corresponding to 0.48 arcseconds of the field of view. To make the maths simpler, I’ll call it 0.5 arcseconds. It’s not going to make a huge amount of difference.

The part of the planet moving fastest across the image plane is at the equator, right in the middle of the image. So how long will it take for a point there to move 0.5 arcseconds? It depends on the period of rotation of the planet and how big it is. For our purposes, the diameter in arcseconds is acceptable as a measurement of size. Simple geometry tells us that any point on the equator must travel πd arcseconds (d being the planet diameter and π being the mathematical constant pi, though it doesn’t look like it in my font) in one rotation, so to find out the time, t, it takes to cover 0.5 arcseconds we need:

t = 0.5p / πd

p being the time for a complete rotation. t will be in the same units as p.

It’s a fairly simple equation, but the fly in the ointment is that as the distances between the Earth and the other planets change so does their angular size, in some cases quite dramatically. As they’re probably the most often imaged, I’ll calculate values for Mars, Jupiter and Saturn here when they’re at their largest apparent diameter.

For Mars, with an apparent diameter between 3.5 and 25 arcseconds and a rotation period of 1477 minutes,

t = 0.5 x 1477 / 25π = 9.4 minutes = 9 minutes 24 seconds.

For Jupiter, apparent diameter between 29 and 50 arcseconds and a rotation period of 595 minutes,

t = 0.5 x 595 / 50π = 1.9 minutes = 113 seconds.

For Saturn, apparent diameter between 15 and 20 arcseconds and a rotation period of 634 minutes,

t = 0.5 * 634 / 20π = 5 minutes.

Obviously if you know the angular diameter at the time you’re actually imaging then you can correct the figures accordingly.

If you have a significantly different plate scale or want to allow for a different amount of drift then the general formula would be:

t = 206265wpk / πfd, where

w is the size of a sensor pixel in metres
p is the period of rotation of the planet
k is the fraction of a pixel allowed for rotational drift (0.5 in my example)
f is the focal length of the telescope in metres
d is the angular diameter of the planet in arcseconds

t will be in whatever units are used for p.

If you’re happy with my assumptions and you’re using an SPC900, but just want to allow for a different focal length then it’s perhaps easiest to start with the following figures and divide by the actual focal length in metres to get the maximum capture time:

Mars: 650 seconds
Jupiter: 130 seconds
Saturn: 350 seconds

Posted in Astroimaging, Astronomy | Leave a comment