4

I trying to toggle one of my GPIO pins at a specific frequency, at the kHz range.

I set up the wiringPi Library, the blinking example seems to work just fine.So I modified the code, so it will oscillat at 35 Khz, but the output frequency is about 5.5 kHz. However when I ran the code with no delay at all the output frequency was 0.5 Mhz. Note that I don't output anything to the screen.

I guess that that this related to the definition of sleeping function "suspends the execution of the calling thread", so returning the thread to the foreground might take some time.

How can I define the precise sleeping time?

  • I tired to use usleep as well an nanosleep, but same problem.
  • All the above was done done via an SSH, as I mentioned, no output was sent during execution
  • The pi is running an Apache server, but I guess it doesn't have a big affect on it

Here is the code I used

#include <wiringPi.h>
#include <stdio.h>
#include <time.h>

int main (void){
  int pin = 7;

  struct timespec time;
  time.tv_sec = 0;
  time.tv_nsec = 14000L;

  if (wiringPiSetup() == -1)
    exit (1);

  pinMode(pin, OUTPUT);

  while(1){
    digitalWrite(pin, 1);
    nanosleep(&time,&time);
    digitalWrite(pin, 0);
    nanosleep(&time,&time);
  }

  return 0;
}

3 Answers 3

5

What you are trying to achieve is almost impossible using operating system. It's really hard to have some hard real time user space mechanism inside operating system. You can try with some RT systems (I don't know if there are some RPi ports) or real time application interface (RTAI, Xenomai, RT Linux) and write some RT module.

nanosleep() suspends the execution of the calling thread until either at least the time specified in *req has elapsed

this means that your timer will least at least time specified, but it could take longer to invoke the timer signal.

3
  • As I suspected :/ , What do you think about a blocking function for a specific time? for instance: while( currentTime() - startTime < delay ); Or should I consider external controlled square wave generator such as 555? Dec 8, 2012 at 15:34
  • I would consider writing kernel module and if that will not give what you want then try external generator. Some usefull info could be found here: mjmwired.net/kernel/Documentation/timers/timers-howto.txt. Take a look especially at usleep_range function. Dec 8, 2012 at 15:44
  • Since I'm not familiar with writing kernel modules, I'd go with an external oscillator, I'll try the usleep_range() method Dec 8, 2012 at 21:34
2

It appears as if you are trying to achieve PWM. For your desired duty cycle you're probably better going after a hardware PWM solution rather than toggle GPIO with user-space delays. The reason for this is that nanosleep reduces to a wait for an interrupt on a hardware timer, which takes a non-negligible about of time to be serviced at user-space.

Here's a good starting point: Can I use the GPIO for pulse width modulation (PWM)?

-1

As @codewarrior said that the nanosleep() will suspend the thread for at least the specified time, so I decided to block the thread rather than return the CPU time to the OS.

Here is my implantation of a precise delay function:

#include <sys/time.h>

void udelay(long us){
    struct timeval current;
    struct timeval start;

    gettimeofday(&start, NULL);
    do {
        gettimeofday(&current, NULL);
    } while( ( current.tv_usec*1000000 + current.tv_sec ) - ( start.tv_usec*1000000 + start.tv_sec ) < us );
}
3
  • This is not "best" solution in case of performance. If you will try to controll more than one pin you could encounter serious limitations. Dec 8, 2012 at 18:18
  • Yes, I know, but I'm using it just one pin for a few millisecond to transmit (modulated IR) a signal.So performance should be an issue here Dec 8, 2012 at 21:30
  • 2
    No. What you have is not a precise delay function. The issue is that even though you don't actively yield to the scheduler by calling a sleep function, you will still get interrupts into the kernel, and the scheduler will still perform context switches to other userspace processes for system housekeeping, which will cause hiccups in your timing. If you used code like this to make an audio tone, and hooked it up to a piezo transducer, you would likely hear periodic gaps when the system is lightly loaded, and grunge when a lot is going on. Nov 14, 2015 at 2:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.