Grove Ultrasonic Ranger Example

This example shows how to use the Grove ultrasonic_ranger on the board. The Ultrasonic sensor has a maximal range of 400 cm, a minimal range of 3 cm and resolution of 1 cm.

If no obstacle is seen by the sensor, 500 cm will be returned by default.

In this notebook, we only show how to control the grove ultrasonic ranger using the Pmod interface. A PYNQ Pmod Grove adapter is required in this notebook. With proper changes in this notebook, users can also control the ultrasonic ranger using the Arduino shield.


In [1]:
from pynq.overlays.base import BaseOverlay

base = BaseOverlay("base.bit")


1. Use Microblaze to control the ultrasonic ranger

The following program assumes that the ultrasonic sensor is attached to the G1 connector of the Pmod Grove adapter, and the adapter is connected to PMODA.

For the timer controller, the control registers are shown as follows:

Register name Register functionality Register value
TCSR0 Timer 0 Control and Status Register 0x00
TLR0 Timer 0 Load Register 0x04
TCR0 Timer 0 Counter Register 0x08
TCSR1 Timer 1 Control and Status Register 0x10
TLR1 Timer 1 Load Register 0x14
TCR1 Timer 1 Counter Register 0x18

In [2]:
%%microblaze base.PMODA

#include "xparameters.h"
#include "xtmrctr.h"
#include "gpio.h"
#include "timer.h"
#include <pmod_grove.h>

#define TCSR0 0x00
#define TLR0 0x04
#define TCR0 0x08
#define TCSR1 0x10
#define TLR1 0x14
#define TCR1 0x18
#define MAX_COUNT 0xFFFFFFFF

void create_10us_pulse(gpio usranger){
    gpio_set_direction(usranger, GPIO_OUT);
    gpio_write(usranger, 0);
    delay_us(2);
    gpio_write(usranger, 1);
    delay_us(10);
    gpio_write(usranger, 0);
}

void configure_as_input(gpio usranger){
    gpio_set_direction(usranger, GPIO_IN);
}

unsigned int capture_duration(gpio usranger){
    unsigned int count1, count2;
    count1=0;
    count2=0;
    XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TLR0, 0x0);
    XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, 0x190);
    while(!gpio_read(usranger));
    count1=XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TCR0);
    while(gpio_read(usranger));
    count2=XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TCR0);
    if(count2 > count1) {
        return (count2 - count1);
    } else {
        return((MAX_COUNT - count1) + count2);  
    }
}

unsigned int read_raw(){
    gpio usranger;
    usranger = gpio_open(PMOD_G1_A);
    create_10us_pulse(usranger);
    configure_as_input(usranger);
    return capture_duration(usranger);
}

2. Do one-time distance measurement

Remember to put some obstacles in front of the sensor, otherwise the default value will be returned.


In [3]:
from pynq import Clocks

def read_distance_cm():
    raw_value = read_raw()
    clk_period_ns = int(1000 / Clocks.fclk0_mhz)
    num_microseconds = raw_value * clk_period_ns * 0.001
    if num_microseconds * 0.001 > 30:
        return 500
    else:
        return num_microseconds/58

In [4]:
read_distance_cm()


Out[4]:
11.873448275862069