Wednesday, April 19, 2006

Stepper motor driver GNU/Linux 2.6 kernel

I started a work on some project related to Stepper Motor Driver in Linux. I found one tutorial at linux gazette online magazine. But to my surprise the driver written was for 2.4.x kernel's. I soon realised that I need to do pretty much stuff in order to make that driver work in 2.6.x kernel. Then again to my surprise I found a excellent tutorial at tldp explaining the 2.6.x and 2.4.x kernel module programming. I went through those tutorials and I ported the driver for 2.6.x kernel.
I used a debian 3.1 sarge with 2.6.8 kernel in it. I started off with some basic differences (between 2.4.x and 2.6.x). Code writing convention has change alot and these days module programmer prefer to use macro's more than anything. They even have macros for defining the init function and the exit function. I went on to learn those things and finally came up with a code which I suppose will work in most of the 2.6.x's series.
Here I present the code:

#include "linux/kernel.h"
#include "linux/fs.h"
#include "linux/module.h"
#include "linux/init.h"
#include "asm/io.h"
#include "asm/uaccess.h"

#define LPT_BASE 0x378
#define DEVICE_NAME "Stepper"
#define DRIVER_DESC "*Stepper Motor Driver*"

static int Major;
static int Device_Open=0;
static int i,j,k=0;
static int pattern[2][4][8] = {
{{0xA,0x9,0x5,0x6,0xA,0x9,0x5,0x6},{0xA,0x8,0x9,0x1,0x5,0x4,0x6,0x2}},
{{0x6,0x5,0x9,0xA,0x6,0x5,0x9,0xA},{0x2,0x6,0x4,0x5,0x1,0x9,0x8,0xA}}
};

void step(void)
{
if(k<8)
{
printk(KERN_INFO "%d\n",pattern[i][j][k]);
outb(pattern[i][j][k],LPT_BASE);
k++;
}
else
{
k=0;
printk(KERN_INFO "%d\n",pattern[i][j][k]);
outb(pattern[i][j][k],LPT_BASE);
k++;
}
}
static int stepper_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Stepper Opened\n");
if(Device_Open)
return -EBUSY;
Device_Open++;
try_module_get(THIS_MODULE);
return 0;
}
static int stepper_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Stepper Released\n");
Device_Open --;
module_put(THIS_MODULE);
return 0;
}
static ssize_t stepper_write(struct file *file, const char *buffer, size_t len, loff_t *off)
{
char data;
get_user(data,buffer);
switch (data)
{
case 'h': /* Half Step */
printk(KERN_INFO "Half-Step mode initialized\n");
j=0;
break;
case 'f': /* Full Step */
printk(KERN_INFO "Full-Step mode initialized\n");
j=1;
break;
case 'F': /* Forward */
i=0;
step();
break;
case 'R': /* Reverse */
i=1;
step();
break;
default: /* Invalid */
printk(KERN_INFO "Invalid argument\n");
break;
}
return -EINVAL;
}
struct file_operations fops = {
.write=stepper_write,
.open=stepper_open,
.release=stepper_release
};
static int __init entry(void)
{
Major=register_chrdev(0,DEVICE_NAME,&fops);
if(Major < 0)
{
printk(KERN_INFO "Cannot get major number for the device %s\n",DEVICE_NAME);
return Major;
}
printk(KERN_INFO "'mknod /dev/%s c %d 0'\n",DEVICE_NAME,Major);
return 0;
}
static void __exit bye(void)
{
int ret = unregister_chrdev(Major, DEVICE_NAME);
if (ret < 0)
printk(KERN_INFO "Error in un-registering stepper: %d\n", ret);
else
printk(KERN_INFO "Stepper un-registered.\n");
}
module_init(entry);
module_exit(bye);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_SUPPORTED_DEVICE(DEVICE_NAME);

The messages logged by this driver can be found in /var/log/messages file. Anytime we need to see what the program does or what it outputs we need to open the file and go down the file to see the recent outputs. This can be made easy by issuing the following command:

tail -f /var/log/messages

As a super user now we need to execute the below command on the terminal. Here the major number is the number allocated by the kernel when the module get's inserted into it. It's a dynamic number. Minor number is mostly 0 (in this case).
In my case I had to execute the following command:

mknod /dev/Stepper c 254 0

This create's a device file in the /dev directory and now if we want to communicate to the motor all we need to do is write data onto this file. That can be done by simply using:

echo "h" > /dev/Stepper
echo "F" > /dev/Stepper
(NOTE: What's happening when these commands execute can be see by tail -f /var/log/messages)

Here data to the stepper device is any valid character in the set {h,f,F,R}. First two elements of the set intializes the motor in half-step or full-step mode and the last two data set actually runs the motor in Forward or Reverse directions.

In the next article I will explain the user interface program I created to handle this motor. I used the power of GTK+ in creating that interface.

Note:
There maybe many points I have left in this article regarding the internal working of the program. For that I assume you have gone through the page .

4 comments:

Anonymous said...

Thanks for this post !!
I'm musician in france and going to use stepper motors to have light animation on stage.

I've read that you plan to make a GUI for this.

But i connot find it, have you already done this ? Do you know where can I find another one, if yours is not done ?

Regards.

Anonymous said...

I don’t know If I said it already but …I’m so glad I found this site…Keep up the good work I read a lot of blogs on Viagra Online a daily basis and for the most part, people lack substance but, I just wanted to make a quick comment to say great blog. Thanks!

Unknown said...

Thank you
I have been trying to work this out for ages. I can now get on with my stepper project.

Thanks
Ron

Anonymous said...

Like you I experienced the same situation back then, due to a physical problem that I had by consuming by mistake generic viagra, I was able to solve the problem after I recovered form that episode.