Measure PPM high time

24 Feb 2012

I recently bought an ultrasonic obstacle sensing system and hacked into it. It uses a PPM signal to determine what sensor (out of four sensors) is sending data, and how far an object is from that signal. It sends 18 pulses, a start pulse (of approximately 1250us), 16 pulses that represent a 0(high time = 125us) or a 1(high time = 250us), and an end pulse.

EDIT: Also, the period of each individual besides the start pulse is 375us.

For example, the 16 pulses could give 1000 0000 0010 1100. This means sensor A (determined from data of first eight bits) has a distance of (data from last eight bits: 0010 1100 = 44 in decimal) 44 cm to an object. These 18 pulses are repeated approximately every 40ms.

Eventually I need to find the start pulse, and then check the high time of the next 16 pulses and save a 0 or 1 so that I can find objects. Currently I am having problems with the microcontroller being fast enough to just output high time of each pulse using this code:

#include "mbed.h"

DigitalIn button(p5);
Serial pc(USBTX, USBRX); // tx, rx
Timer t;

int i = 0;

int main() {
    t.start();
    while(1) {
        while(!button);
        t.reset();
        while(button);
        pc.printf("%d\n", t.read_us());
    }
}

This will give me an output of 1249 247 1249 248 1249 ... ... So it seems to only have time to read the start pulse, then read the next pulse, and then it's already to the next set of data. Any suggestions on a faster way to do this?

Thanks, Trent

24 Feb 2012

I figured out the problem, but thought I would post my solution so other new mbed users would see what I ran into. The pc.printf function takes a very long time to finish, so instead of printing every pulse time, I saved the times in an array. Then, after saving so many sequences, I stopped checking for pulses and moved into a for loop that printed off the values of the arrays. This worked exactly how I needed it to. The following code finds and prints the sensor that sent the data and the distance to an object for that sensor:

#include "mbed.h"

DigitalIn button(p5);
Serial pc(USBTX, USBRX); // tx, rx
Timer t;

unsigned int values[990];   //990 is a random number that is a multiple of 18. the number determines
                            //how many pulse sequences will be checked (990/18 = 55 sequences)
unsigned int i = 0;
unsigned int distance, sensor;

int main() {
    t.start();  //start timer outside while loop to save time
    while (i < 990) {   //we want 990 pulses saved, which should give 55 sequences
        while (!button);    //wait for rise
        t.reset();          //reset timer to 0
        while (button);     //wait for fall
        values[i] = t.read_us();    //read the timer value and save in array
        i++;
    }
    for (int k = 0; k < 990; k++) {     //replace pulse time with bit representation
        if (values[k] > 375)         //if greater than 375, it is start bit
            values[k] = 2;           //so give random number 2 so we can find start pulse later
        else if (values[k] > 175)    //greater than 175 is high
            values[k] = 1;
        else if (values[k] < 175)    //less than 175 is low
            values[k] = 0;
    }
    for (int j = 0; j < 990; j++) {
        while (values[j] != 2)  //sort through values to find start bit
            j++;
        sensor = values[j+7] * 2 + values[j+8];     //7th and 8th bits contain sensor data
        distance = values[j+9] * 128 + values[j+10] * 64 + values[j+11] * 32 + values[j+12] * 16 + values[j+13] * 8 + values[j+14] * 4 + values[j+15] * 2 + values[j+16];
                //9th through 16th bits contain distance data
        if (distance < 256) {   //only print values within correct range
            if (sensor == 0)
                pc.printf("Sensor A  %d cm\r\n", distance);
            if (sensor == 1)
                pc.printf("Sensor B  %d cm\r\n", distance);
            if (sensor == 2)
                pc.printf("Sensor C  %d cm\r\n", distance);
            if (sensor == 3)
                pc.printf("Sensor D  %d cm\r\n", distance);
        }
    }
    while (1);
}

This code can easily be turned into a function that is called from a main loop that will check a certain amount of pulse sequences and find the distance to objects for each sensor.

Thanks, Trent