AR Drone 2/Multidirectional distance measurement

From PaparazziUAV
Jump to: navigation, search

Sensor Choice

In order to be able to fly autonomously in an unknown environment the drone has to be able to detect objects and measure their distance. At first we wanted to do these measurements using LIDAR, a laser based measurement system. However we soon realised that this would be way to expensive for us to even consider. Previous robotics projects at the TU Delft made successful use of the kinect system, stripping it to its components and using its sensors, so this became our second option. We had to eliminate this option as well unfortunately because even stripped, the kinect was simply too heavy for our flying platform.

The options left to us were using multiple sensors. These could either be sonar, infrared or video (stereoscopy). We evaluated each of them by price, added weight and power consumption. Eventually we settled for infrared sensors. These were affordable, very lightweight and didn't consume that much energy.

Sharp IR Sensor

The IR sensor that was chosen, specifically, was the Sharp GP2Y0A710K0F, many specifics for the sensor can be seen in the datasheet. Sensors will be used to point forward, backward, left, and right of the drone, measuring distance in each of these four directions. Dependent upon certain restrictions, namely weight and power consumption, there is also the potential benefit of directing one sensor upward to complement the existent ultrasonic downward facing sensor. Analog voltage data coming from the sensors will have a corresponding distance, this voltage versus distance relationship can be seen in the graph to the right.

Voltage v. Distance graph for Sharp IR Sensor

Obtaining Sensor Data

Instead of trying to connect them directly to the AR Drone board, which offers very little in terms of modifications, we decided to use a LPCxpresso board to mount them on and use an USB interface to connect this to the AR Drone board. In essence, the main function of the LPCxpresso board is to receive an analog voltage signal from each of the infrared sensors, convert that to a digital voltage value by way of analog to digital converter, and organize that data into a convenient and efficient form for eventual transferring via USB to the AR Drone board.

LPCxpresso LPC1769

An example LPCXpresso board

The LPC1769 was chosen because out of the NXP microcontroller family, it has the most similar instruction set as AR.Drone's processor. It also has five analog to digital convertors and enough flash memory for storage of all coding, the ability for a USB connection to the AR Drone main board, and a €20 price point. Although the price point was initially a factor, the board was later donated by the Delft University of Technology EWI faculty.

Software and Processing

Accompanying the LPCXpresso is an Eclipse based Integrated Development Environment (IDE); Software is written in the C programming language. Another benefit to using the LPC board is the extensive example library that can be downloaded from the NXP website, also worth considering but of less help is the LPC Knowledge Base forums, also on the NXP website. The example library is extensive enough such that code for an analog to digital converter (ADC) is readily available. In an effort to work efficiently, the group made use of these example projects.

main.c Clarification

A majority of the working code was written in a main C file which was appended and headed by various, established header files. What follows are various sections of the main.c file and an explanation as to what their function is with respect to the function of the code. The following include statements are used to define some basic aspects of the file; stdint.h defines a standard integer width; stdio.h is the standard C input and output library; adc.h is the library that will be used for the analog to digital converter.

This project is using the LPC1769 Rev. B board and therefore the coding is written to work with that board. That being said, the code is easily adaptable to other hardware, particularly, other LPC boards and mbed boards. Including lpc17xx.h header file identifies which ports are available to the code and which ports can be called. Finally, the last three include statements for USB libraries are for the inputting and outputting of data from the USB port on the target board. Lastly, two integers are defined for the ADC and system timer along with a defined ADC filter size and binary size.

#include <stdint.h>
#include <stdio.h>
#include "adc.h"
#include "lpc17xx.h"
#include "LPCUSBlib/Drivers/USB/USB.h"
#include "LPCUSBLIB/Drivers/USB/Class/Device/CDCClassDevice.c"
#include "LPCUSBLIB/Drivers/USB/Class/Device/CDCClassDevice.h"

extern volatile uint32_t ADCIntDone;
extern uint32_t rit_timer_counter;
const int BINARY_SIZE = 12;
#define FILTER_SIZE 20

In early testing of the sensors it was noted that spikes in the voltage data were not uncommon; these spikes could lead to incorrect readings and it was therefore decided that the spikes in data could be mitigated by setting a certain range of values which could be averaged, in essence, a smoothening of the data. As defined above, the filter size was determined best at 20 readings, this is also set as the window length; current is the current reading at the end of the window. The filter system is initialized, the code can be seen below.

struct filter_structure
{
	uint32_t window[FILTER_SIZE];
	uint32_t current;
};
typedef struct filter_structure filter_t;

/* Initialize filter structure
 */
void init(filter_t* filter)
{
	int i;
	filter->current = 0;
	for (i = 0; i < FILTER_SIZE; i++)
		filter->window[i] = 0;
}

As the data passes through the filter it keeps a running average of the last 20 readings, these averages are calculated in the following code. It should be noted that the main section the main.c file operates in a continues loop from which the average function is called through each iteration. The current window value is appended to the running sum which is then divided by the window value.

/* Generate an average from the given input
 * and return that value
 */
uint32_t average(filter_t* filter)
{
	uint32_t sum = 0;
	uint32_t i;
	for (i = 0; i < FILTER_SIZE; i++)
		sum += filter->window[i];
	return sum / FILTER_SIZE;
}

Lastly, the filter increments its current reading and continues to the next reading.

/* Increment the given filter 
*/
void increment_current(filter_t* filter)
{
	filter->current++;
	if (filter->current == FILTER_SIZE)
		filter->current = 0;
}

The performance of the filter can be seen in the following two graphs. These two cases used a window size of 20 readings to find a running average; it was found that this window size was the best middle ground between the ability to sense actual distance variations while still taking a large enough average to quell any sudden voltage errors. Do note that the sensor was motionless in this measurement period and the fluctuations are purely in error, not in actual distance changes.

Filtered v. Unfiltered performance graph 1
Filtered v. Unfiltered performance graph 2

Hardware Wiring

The LPC1769 offers many ports for a wide variety of functions and tasks; this project does not utilize all but does involve a bit of wiring. It is advisable and suggested to first test all of the wiring on a breadboard. In researching wiring arrangements, the LPC1769 Pin Function table was found to be quite useful in addition to the LPC1769 Schematic.