Autonomous Racing Rotorcraft: Initial Camera Exploration: I2C Smoke Test
I am now far far down the rabbit hole of trying to validate a camera for the low altitude altimetry of my prototype autonomous racing helicopter. In the last post I got to the point where I could build system images for my IGEP COM Module that included patches on top of the ISEE 3.6 linux kernel. The next step was to use that ability to turn on the clock at the TI DM3730’s external camera port.
First, what is the path by which a normal camera driver turns on the clock on the IGEP? To discover this, I traced backwards from the board expansion file for the CAMR0010 produced by ISEE, just because it was the easiest place with a thread to start grasping. In the board expansion file, “exp-camr0010.c”, a function is defined specifically to configure the ISP’s (Image Signal Processor) clock:
static void mt9v034_set_clock(struct v4l2_subdev *subdev, unsigned int rate)
{
struct isp_device *isp = v4l2_dev_to_isp_device(subdev->v4l2_dev);
isp->platform_cb.set_xclk(isp, rate, ISP_XCLK_A);
}
However, in the absence of a full camera driver, it was not entirely clear how to get a hold of a “struct isp_device*” that you could use to configure the clock. To understand more, I traced the many layers this function is passed down through before leaving the board expansion source file:
- mt9v034_platform_data: This structure was defined by ISEE and is exposed from the new mt9v034 driver.
- i2c_board_info: The mt9v034_platform_data structure is passed into this one as the “.platform_data” member.
- isp_subdev_i2c_board_info:The i2c_board_info structure is passed as the “.board_info” member of this structure.
- isp_v4l2_subdevs_group_camera_subdevs: The board_info structure is passed in here as the “.subdevs” member.
- isp_platform_data: The camera_subdevs member is passed in here as the “.subdevs” member.
- omap3_init_camera: Finally, the platform_data structure is passed in here.
Eventually, this clock setting callback is stashed inside the mt9v034 driver where it is invoked in a couple of places. Yikes! I tried to backtrack this route to get an isp_device, but had no luck. What did end up working was grabbing the driver, then device by name: (error checking and the “match any” function omitted for clarity)
struct device_driver* isp_driver;
struct device* isp_device;
struct isp_device* isp;
isp_driver = driver_find("omap3isp", &platform_bus_type);
isp_device = driver_find_device(isp_driver, NULL, NULL, match_any);
isp = dev_get_drvdata(isp_device)
Then, I exposed this functionality through a simple debugfs entry that appears in /sys/kernel/debug/arr_debug/xclka_freq (when debugfs is mounted of course). Then I was able to write frequencies from the command line and get the external clock to run at any frequency I chose. Yay!
There was one final piece to the puzzle before I could claim the camera was functional. The OV9650, while electrically compatible with I2C, is not an SMBus device. The standard linux command line tools, i2cget and friends were not able to drive the camera in a useful way. To get over the final hurdle, I wrote a simple user-space C program which opens “/dev/i2c-3”, sets the slave address using the I2C_SLAVE ioctl, and then uses the bare “read” and “write” API to send and receive bytes of data. With this, I was able to extract the product identifier from the chip of 0x9652! I guess it is likely a subsequent revision of the 9650.




The toolchain I used could be applied to a number of 3D projects. First, I either found an image kind of resembling what I had in mind using google images, or drew up a sketch on a piece of paper. Then, I transcribed that image into an
Next, I fired up 





First, a little background. The motor controller on Savage Solder is the stock 
For the last 6 years I have ever so slowly been learning how to fly medium sized RC helicopters outdoors, in an attempt to become a good enough pilot that I could roboticize one. About a year ago I upgraded to a Blade 450, which let me practice outdoors in a much wider variety of weather conditions and provided for a feasible amount of payload. My proficiency is now good enough that I’ve started work on the control and navigation design with the medium term goal of entering it in autonomous racing competitions, such as