Pages

Sunday, April 15, 2012

Before I go to bed, I want to share a linux device driver I wrote sometime back for an old Zichuan ZCC210N I2C compass. Unfortunately, it stopped working before I could test the driver. I don't have the tools to debug the module, but the driver compiles and loads fine. Since, this was one of the early compass modules available in hobby stores, I thought someone out there might find this code useful.


#include 
#include 
#include 
#include 

#define ZCC210_I2C_ADDRESS   0x60
#define ZCC210_DIRECTION_COMMAND 0X77
#define ZCC210_DRIVER_NAME   "zcc210"

/* Addresses to scan */
static const unsigned short normal_i2c[] = {ZCC210_I2C_ADDRESS, I2C_CLIENT_END};

/*Device interface functions*/
static s32 zcc210_read_direction(struct i2c_client *client)
{
    /* Read direction bytes*/
    return i2c_smbus_read_word_data(client, ZCC210_DIRECTION_COMMAND);
}

/*sysfs callback functions*/
static ssize_t show_values(struct device *dev, struct device_attribute *attr, char *buf)
{
 struct i2c_client *client = to_i2c_client(dev);

    s32 result = zcc210_read_direction(client);

    if(result > 0){
        return sprintf(buf, "%d\n",
                (s32)swab32((u32)result));
    }
    return result;
}

static DEVICE_ATTR(values, S_IRUGO, show_values, NULL);

//static struct i2c_board_info zcc210_i2c_board_info = {  
//   I2C_BOARD_INFO(ZCC210_DRIVER_NAME, ZCC210_I2C_ADDRESS),      
// };

static struct attribute *zcc210_attributes[] = {
 &dev_attr_values.attr, 
 NULL
};
 
static const struct attribute_group zcc210_attr_group = {
.attrs = zcc210_attributes,
};

static const struct i2c_device_id zcc210_id[] = {
    { ZCC210_DRIVER_NAME, 0},
    {}
};

static int zcc210_detect(struct i2c_client *client, struct i2c_board_info *info)
{ 
 if (client->addr != ZCC210_I2C_ADDRESS)
 return -ENODEV;
  
 strlcpy(info->type, ZCC210_DRIVER_NAME, I2C_NAME_SIZE);
 return 0;
}

static int zcc210_probe(struct i2c_client *client, const struct i2c_device_id *id)
{  
 int err;
 
    printk(KERN_INFO "%s: new instance found!\n", ZCC210_DRIVER_NAME);

 /* Register sysfs hooks */
 err = sysfs_create_group(&client->dev.kobj, &zcc210_attr_group);
 if (err)
 {
  return err;
 }

 return 0;
}

static int zcc210_remove(struct i2c_client *client)
{
 sysfs_remove_group(&client->dev.kobj, &zcc210_attr_group); 
    return 0;
}

static struct i2c_driver zcc210_driver ={
    .driver.name = ZCC210_DRIVER_NAME,
    .id_table = zcc210_id,
    .probe = zcc210_probe,
    .remove = zcc210_remove,

 .class = I2C_CLASS_HWMON,
 .detect = zcc210_detect,
 .address_list = normal_i2c,
};

static int __init zcc210_init(void)
{
    printk(KERN_INFO "%s: init!", ZCC210_DRIVER_NAME ); 
 return i2c_add_driver(&zcc210_driver);
}

static void __exit zcc210_exit(void)
{
    printk(KERN_INFO "%s: exit!", ZCC210_DRIVER_NAME );
 i2c_del_driver(&zcc210_driver);
}

MODULE_AUTHOR("Karthik S Prakash <karthik.s.prakash@yahoo.com");
MODULE_DESCRIPTION("Zhichuan ZCC210 I2C Compass driver");
MODULE_LICENSE("GPL");

module_init(zcc210_init);
module_exit(zcc210_exit);


RichToolTip in C#

I wanted to display some important test results on Datagrid cells. But the default cell tooltip displays only plain texts. A rich text box would allow me to format my results in a easy to read form highlight PASS/FAIL etc.

I found a couple of useful links:
  1. MFC based: RichText Tool-tip Control
  2. An awesome HTML tooltip A Professional HTML Renderer You Will Use
Then I came across this - How to print the content of a RichTextBox control by using Visual C# - a printable rich text box. I remembered that while investigating the C# ToolTip class methods earlier, I had figured out it could display images... voila!

Below is the tool tip implementation I came with using the printable rich text box control above:

public class RichToolTip : ToolTip
    {
        Size toolTipSize = new Size();

        /// 
        /// Gets or sets the RichTextBoxPrintCtrl to show as tool tip
        /// 
        public RichTextBoxPrintCtrl RtbPCtrl { get; set; }

        public RichToolTip()
        {
            OwnerDraw = true;
            Popup += new PopupEventHandler(RichToolTip_Popup);
            Draw += new DrawToolTipEventHandler(RichToolTip_Draw);
            RtbPCtrl = new RichTextBoxPrintCtrl();
        }

        void RichToolTip_Draw(object sender, DrawToolTipEventArgs e)
        {
            e.Graphics.Clear(Color.White);

            using (Image image = new Bitmap(toolTipSize.Width, toolTipSize.Height))
            {
                using (Graphics g = Graphics.FromImage(image))
                {
                    RtbPCtrl.Print(0, RtbPCtrl.Text.Length, g, new Rectangle(RtbPCtrl.Location, toolTipSize));
                }
                e.Graphics.DrawImageUnscaled(image, e.Bounds);
            }
        }

        //Fires before the draw event. So set the tooltip size here.
        void RichToolTip_Popup(object sender, PopupEventArgs e)
        {
            using (Graphics g = RtbPCtrl.CreateGraphics())
            {
                toolTipSize = g.MeasureString(RtbPCtrl.Rtf.Trim(), RtbPCtrl.Font).ToSize();                
                e.ToolTipSize = toolTipSize;
            }
        }
    }


Tuesday, July 26, 2011

How to resolve - "HttpWebRbRequest: The request was aborted: The request was cancelled." error.

Yesterday, I came across this new error message when doing HttpWebRbRequests in C# (.NET 3.5).

After doing a quick search, I see that it is a common problem with several solutions that has worked for different applications. This link here points to different solutions: HttpWebRequest: The request was aborted: The request was canceled

In my application, I have upto 16 identical threads doing simultaneous HTTP requests. However, each of these threads are requesting from different webservers along with unique local endpoints. Now the function making these calls has 3 successive HTTP requests to make (to the same webserver).

None of the above solutions worked for me, but the following combination did however.


System.Net.ServicePointManager.DefaultConnectionLimit = 200;
System.Net.ServicePointManager.MaxServicePointIdleTime = 2000;
System.Net.ServicePointManager.MaxServicePoints = 1000;
System.Net.ServicePointManager.SetTcpKeepAlive(false, 0, 0);

HttpWebRequest webRequest1 = (HttpWebRequest)WebRequest.Create("http://" + gatewayIP
 + "/xslt?PAGE=J04");
webRequest1.KeepAlive = false;
webRequest1.Timeout = 2000;
//Do other stuff here...
//Close response stream

Thread.Sleep(2000); //This delay seems to help.

HttpWebRequest webRequest2 = (HttpWebRequest)WebRequest.Create("http://" + gatewayIP
 + "/xslt?PAGE=J04");
webRequest2.KeepAlive = false;
webRequest2.Timeout = 2000;
//Do other stuff here...
//and so on...




Monday, June 6, 2011

Mobot keeping an eye out for green things...

Mobot is attracted by round green things. Here is a candid video.



Notice the jitter in the servo used for up/down motion of the eye. This most often due to noise. However, in this case, I believe it's due to the servo itself. It has shown this behavior even when kept away from other circuits.

Sunday, May 29, 2011

A MoBot is born!

Say hello to my little friend!!


Mobot here is based on the Rover 5 chassis with four motors and encoders. It's motors are controlled by a Pololu Qik 2s9v1 Dual Serial Motor Controller. To keep cost down and also improve battery life, I am using only 2 of the motors. So I had to remove a key gear in the other two motor boxes to keep them free running.

The Qik Serial appears as a serial port in the Beagleboard and commands could sent simply by writing on the port file. In my case it was "/dev/ttyS1".

The encoders are level shifted and connected to the Beaglebaord's GPIO pins. A single thread running 1000 times a second keeps track of the quadrature encoder counts.

I have incorporated a PID loop for speed control and another PI loop for position control. The algorithm was derived from the book Embedded Robotics by Thomas Bräunl which has an excellent chapter on PID control for differential drive robots.

Mobot has a Logitech C120 webcam for an eye and can look around using a servo pan-tilt bracket.

Sunday, February 27, 2011

Ball Tracking with OPENCV

Again, mechomaniac's article gave me jump-start to tracking a ball.

Below is a video of the code in action. I had to tweak parameters to the cvHoughCircles() function and the HSV thresholds to prevent false detection.



An important thing to note is that OpenCV's HSV format stores the Hue component as an 8-bit integer in the range of 0-179. This is unlike other graphics software which use Hue values from 0-255.

I observed the following frame rates:

Frame rates vs Resolution
Resolution With Hough Circle detection Without Hough Circle detection
320x240 ~5fps ~9fps
640x480 ~2fps ~4fps

Based on the benchmark here, I agree with the author that there might be a USB bandwidth limitation that is resulting in low frame rates. I am looking at using the DSP on the board to speed up OpenCV and use a direct interface to a camera to acquire images.

Sunday, January 30, 2011

Camera capture using OpenCV

I had a Logitech C120 camera lying around and found that Angstrom had drivers for it. It was about 1:00am and I couldn't wait till I captured an image.

OpenCV is a popular library for image processing. I found this post which got me started with OpenCV. But you must also install opencv-dev to get the header files or the program will not compile.

To get OpenCV:

opkg update
opkg install task-native-sdk cpp gccmakedep
opkg install python-distutils python-compile python-compiler python-devel
opkg install ffmpeg-dev
opkg install opencv
opkg install opencv-dev
My wireless connection was not very good, so I got several package download failures with "wget returned 1". I just switched to USB Ethernet and it went smooth.

Also, if you get "But that file is already provided by package xxx" errors while installing opencv-dev, just uninstall opencv and try again from step 5. I am not sure what the problem was, but it worked the second time.

Finally, around 3:00am I captured the first images. I went to bed both satisfied and eager to get back to my desk and track a ball or something!