Friday, April 30, 2010

PWM generation in BeagleBoard

My primary interest to make a robot centred around BeagleBoard is incomplete without generating PWMs to control DC motors and Servos. Since Beagleboard has all what it takes to make a robot, I am not going to be bothered to have a microcontroller to aid Beagleboard.

My requirement is like this - say an image processing algorithm is running on Beagleboard, and at end of every iteration I want to update the speed of motors by changing the PWM values. In the meantime when the Vision algorithm is running, the board should keep on generating the PWM until it's value is changed.

It started with searching the community for info and this post is quite helpful. this one also is quite helpful. When I first tried all sort of permutations and combinations according to these information, it just didn't work. The file in which we are supposed to write the values like direction, value would give no write excess error. This problem was due to drivers not loaded i.e. this problem got solved when we compiled a new kernel with drivers of TPS320* which handles these IO functionalities.

Now the basic checks like making a pin high or low starts to work. To make a code to suits the above requirement, we went ahead with multi-threading. one thing to just remind here is that, in Linux these port operations are done through writing and reading appropriate files.

In the above code, in new_code.c the main algorithm will be running in place of the three nested for loops.
We have created two threads one for each pwm, and created a structure having parameters time_h and time_l denoting high time and low time. Whenever we want to change the value of PWM we change the value of these two parameters.

Once each iteration of the algorithm completes, we change the value of time_h and time_l for both the PWMs.

in waveform.c we perform the toggling of pin ON-OFF manually in the code by writing to the file named value. [Beware that before even executing the program you have to do some initialisation manually which have not been done in code, these are mentioned at the end]

Since these are multithreaded files the compilation is doen by
gcc new_main.c -lpthread

Initialisation needed Before Executing
You need to do the following things:-
1. Create directory for your IO pin/s
2. Set its direction (as output in our case)

The code above looks like clean POSIX to me. It should work on similarly on all Linux-es running the same kernel. If you have a different kernel, your response time might be different, but the effects of the kernel differences will likely be minimal compared to the other processes that you may have running in userspace.