5

I want to write a program that controls a servo motor myself using a pi B+. Controlling the motor involves sending 1.5 millisecond pulses along a GPIO pin every 20 milliseconds. I have tested the following stripped-down code on a 32-bit x86 Ubuntu machine and the B+, and I get very different results. I compiled both with gcc.

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

int main()
{
    int num;
    long int signalTime = CLOCKS_PER_SEC * 3/2/1000; /* clocks in a 1.5 millisecond clock pulse */
    long int twentyMilliSec = CLOCKS_PER_SEC / 1000 * 20;
    clock_t start = clock();
    for (num = 0; num < 20; num++)
    {
        /* turn it on right here */
        printf("Turning on: %ld\n", clock() - start);
        while ((clock() - start) % twentyMilliSec  < signalTime)
            ;
        /*turn it off right here*/
        printf("Turning off: %ld\n", clock() - start);

        /* now we wait until 20 milliseconds is done */
        while ((clock() - start) % twentyMilliSec > signalTime)
            ;

    }
}

on the x86, I get the following output. Each number is 1 microsecond.

Turning on: 2
Turning off: 1501
Turning on: 20001
Turning off: 21501
Turning on: 40001
Turning off: 41501
Turning on: 60001
Turning off: 61501
Turning on: 80000
Turning off: 81500
Turning on: 100000
Turning off: 101500

Which is what I want, 1500 microsecond pulses with 20000 microsecond gaps between them. On the pi, I get the following.

Turning on: 0
Turning off: 10000
Turning on: 20000
Turning off: 30000
Turning on: 40000
Turning off: 50000
Turning on: 60000
Turning off: 70000
Turning on: 80000
Turning off: 90000
Turning on: 100000

It appears that the clock in is only accurate to 10000 microseconds. How can I get a clock in C that gives me enough precision to control a servo? I know it can be done, since there are C libraries that control servos for you.

axl
  • 153
  • 3

3 Answers3

4

Use gettimeofday(), it returns seconds and microseconds.

You are unlikely to get satisfactory results for servos using Linux sleeps. There will be glitches. Unless you have a particularly poor servo the glitches will result in servo twitches.

A B+ has two channels of hardware PWM suitable for driving servos.

The C libraries which generate hardware timed PWM on all the gpios use paced DMA to time the pulses.

joan
  • 71,852
  • 5
  • 76
  • 108
0

Sorry, but that will not work. Even if you tune the OS into the extremity, the servo will always wiggle about. I've done a lot of servo controlling myself, but using Atmel AVR microcontrollers (the ones used in Arduino's). You're way better off using a simple Arduino to control the servo('s).

I usually created an interrupt off a timer that would time 8 servo channels in a single go. The 1-2ms pulses would leave the pins one-by-one, but as long as the repeating frequency is 20ms you're fine (btw that is why I control 8 servo's - 8x2ms = 16ms which falls within the 20ms repeating frequency).

Maybe add a Pi to do any high-level stuff and telling the Arduino how to position the servos... If needed at all...?!?

Erik Z
  • 308
  • 2
  • 6
0

My PI v2 running raspbian jessie gives me:-

Turning on: 9
Turning off: 1502
Turning on: 20004
Turning off: 21503
Turning on: 40003
Turning off: 41504
Turning on: 60002
Turning off: 61503
Turning on: 80002
Turning off: 81502
Turning on: 100003
Turning off: 101502
Turning on: 120003
Turning off: 121502
Turning on: 140003
Turning off: 141502

etc etc etc So it seems to work.

joan
  • 71,852
  • 5
  • 76
  • 108