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;
}
Kirill Kulakov
  • 139
  • 1
  • 4

3 Answers3

4

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.

codewarrior
  • 491
  • 2
  • 7
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 );
}
no id
  • 169
  • 1
  • 9
Kirill Kulakov
  • 139
  • 1
  • 4