Wednesday, November 7, 2012

panda and beagle board


Panda
http://pandaboard.org/content/resources/getting-started
http://pandaboard.org/content/new-pandaboard-es-arms-open-source-mobile-developers-ti%E2%80%99s-omap4460-processor
http://pandaboard.org/content/resources/references
http://omappedia.org/wiki/PandaBoard_FAQ
http://en.wikipedia.org/wiki/BeagleBoard

http://www.liquidware.com/shop/show/BB-XM/BeagleBoard+XM









http://www.ozbotz.org/a-simplereal-time-application-on-pandaboard/


A Simple Realtime Application on the PandaBoard:
A 10 KHz Square Wave

This post contains code that creates a 10 KHz square wave on one of the GPIO pins of a PandaBoard running the real-time Linux extensions. It is a proof of concept showing that the PandaBoard is suitable for real time applications.
The code used in this example is based on the swave.c program from the kernel.org RT wiki, which is located here:https://rt.wiki.kernel.org/articles/s/q/u/Squarewave-example.html.
For instructions on how to run realtime Linux on your PandaBoard, refer to the tutorial that I posted on the Homebrew Robotics Club wiki titled “Installing Ubuntu With Real Time Patches On The PandaBoard.”

Code

The following code is all that you need to create the square wave. Save the code in a file called swave_panda.c.
// file: swave_panda.c
/* compile using  "gcc -o swave_panda swave_panda.c -lrt -Wall"  */

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sched.h>
#include <sys/io.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define NSEC_PER_SEC    1000000000

/* using clock_nanosleep of librt */
extern int clock_nanosleep(clockid_t __clock_id, int __flags,
      __const struct timespec *__req,
      struct timespec *__rem);

static inline void tsnorm(struct timespec *ts) {
    while (ts->tv_nsec >= NSEC_PER_SEC) {
        ts->tv_nsec -= NSEC_PER_SEC;
        ts->tv_sec++;
    }
}

int main( int argc, char** argv )
{
    struct timespec t;
    struct sched_param param;
    int interval=50000;  // 50000ns = 50us, cycle duration = 100us

    int fd;
    char zero_string[] = "0";
    char one_string[] = "1";
    char buffer[32];
    unsigned char value = 0;

    // Enable GPIO_32, which comes out pin 18 of J6. A list of available GPIOs
    // can be found in the PandaBoard System Reference Manual.
    {
        if ((fd = open("/sys/class/gpio/export", O_WRONLY | O_NDELAY, 0)) == 0) {
            printf("Error: Can't open /sys/class/gpio/export.\n");
            exit(1);
        }   
        strcpy( buffer, "32" );
        write( fd, buffer, strlen(buffer) );
        close(fd);
        printf("Added GPIO 32.\n");
    }

    // Set the direction of the GPIO to "out."
    {
        if ((fd = open("/sys/class/gpio/gpio32/direction", O_WRONLY | O_NDELAY, 0)) == 0) {
            printf("Error: Can't open /sys/class/gpio/gpio32/direction.\n");
            exit(1);
        }
        strcpy( buffer, "out" );
        write( fd, buffer, strlen(buffer) );
        close(fd);
        printf("Direction set to out.\n");
    }

    // Open the "value" node. We will write to it later.
    {
        if ((fd = open("/sys/class/gpio/gpio32/value", O_WRONLY | O_NDELAY, 0)) == 0) {
            printf("Error: Can't open /sys/class/gpio/gpio32/value.\n");
            exit(1);
        }   
        printf("Value opened for writing.\n");
    }

    if ( argc >= 2 && atoi(argv[1]) > 0 ) {
        printf("Using realtime, priority: %d.\n",atoi(argv[1]));
        param.sched_priority = atoi(argv[1]);
        // Enable realtime fifo scheduling.
        if(sched_setscheduler(0, SCHED_FIFO, &param)==-1){
            perror("Error: sched_setscheduler failed.");
            exit(-1);
        }
    }
    if ( argc >= 3 )
        interval=atoi(argv[2]);

    clock_gettime(0,&t); // Get current time.
    t.tv_sec++;          // Start after one second.

    while (1) {
        // wait untill next shot.
        clock_nanosleep(0, TIMER_ABSTIME, &t, NULL);
        if(value) {
            write( fd, one_string, 1 );
            //printf("...value set to 1...\n");
        } else {
            write( fd, zero_string, 1 );
            //printf("...value set to 0...\n");
        }
        value = !value;
        // Calculate next shot.
        t.tv_nsec+=interval;
        tsnorm(&t);
   }
   return 0;
}
Compile the program with the following command:
gcc -o swave_panda swave_panda.c -lrt
To run the program with a real time priority of 90, enter the following command:
sudo ./swave_panda 90

Hardware Setup

To view the output on a oscilloscope, connect the probe to pin 18 on J6. You can find ground on pins 27 and 28 of J3.

Results

After you run the program and connect your oscilloscope probe to pin 18, you should see a 10 KHz square wave, as shown in the following image.
The square wave is solid even when the system is under moderate load. Under heavy load, I can see a jitter of a few microseconds. I have yet to determine from where the jitter originates. I don’t know if there is some uncertainty in the kernel or if there is a uncertain amount of delay in the userspace GPIO drivers. None of my robots operate in conditions that are dangerous to humans or property, so I will probably be able to tolerate an uncertainty of a few microseconds. If you are designing a surgical robot, for example, a few microseconds of uncertainty might be too much. I will be investigating if this little bit of observed jitter can be reduced or eliminated.

More Informaion

I am interested in creating more realtime applications for the PandaBoard. If you have any experience creating such programs and you have any advice to offer or you would like to exchange ideas, please send me an email or add a comment to this post.

3 comments to A Simple Realtime Application on the PandaBoard:
A 10 KHz Square Wave

  • Andrés
    Excellent article :D
    I have a question tho. I’m currently working with the pandaboard running Android 4.0.3, so far it has worked pretty well and the apps I’m building run smooth with almost no problems.
    Recently I began to code an application and I need to make use of the GPIO ports the pandaboard has. I could successfully run a script which generates a square signal of 100 Hz (low freq) but the signal is not consistent at all, this makes me think it is due to the kernel not being a real-time one. Do you know if it is any possibility to patch my android build with a real-time kernel?
    Hope you could give me a hand on this :D
    • Osman Eralp
      Moving to a real time kernel will definitely help. A Linux OS can sometimes “go away” for a hundred(s) milliseconds doing things like file clean up. This will cause jitter even on your slow square wave. You would first need to find the source for your build. If it is built on the source from kernel.org, you have a chance at being able to apply the real time patches. Unfortunately, I have not tried this for Android, so I can’t provide any specific advice. Sorry!
  • Andrés
    Thank you Osman for replying so fast!
    I will try to find the way to patch my already built kernel. I guess moving to a RT kernel should not interfere with Android, but I will let you know if I’m successfull at this.
    Again, you were of a lot of help, now I have a clue on what to do in order to make my app to work as intended.
    Rgds
    Andrés



No comments:

Post a Comment