2D Plotter

The idea of this project was to create an ultrasonic radar by mounting an ultrasonic sensor on a stepper motor. 

The plan was that the stepper motor will step from 0 – 360 degrees, the ultrasonic sensor will record the distance reading on each step and then plot the recorded data using Python and Matplotlib. 

This is the circuit of the system:

Radar Drawing

This is my c code:


// Ultrasonic stepper-motor Radar Project
// Written by Aron Horan
// Last updated 21-11-2013
 
#include 
#include 
#include 
#include 
 
// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, Fcy=30MHz
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin
 
int step_counter = 0;
int angle = 0;
int get_distance();
void step_forward();
void step_back();

// create a 2D pixel array with 100 rows & 100 columns
int distance[800];

int main()
{
	int x, y, d, cm, state, reverse=0, forward=1, n;
	state = forward;

	// Configure UART
	U1BRG = 48;            // 38400 baud @ 30 MIPS
	U1MODEbits.UARTEN = 1; // Enable UART

	// Make all port D pins outputs
	TRISD = 0;
	// Make RF0 an output
	TRISF = 0b10;

	// Configure Timer 2
	T2CONbits.TCKPS = 0b10; // Timer 2 prescaler 1:64
	PR2 = 9375;             // Timer 2 period (20ms)
	T2CONbits.TON = 1;      // Enable Timer 2

	
	while(1)
	{
		d = get_distance();
		distance[step_counter] = d;

		if(state == forward) // rotate clockwise until angle = 360 degrees
		{
			step_forward();
			if (step_counter == 799) state = reverse;
		}
		else if(state == reverse) // rotate anticlockwise until angle = 0
		{
			step_back();
			if (step_counter == 0) state = forward;
		}

		if (step_counter == 0 || step_counter == 799)
		{
			// Transmit all readings to PC
			for (n=0 ; n<800 ; ++n)
			{
				printf("%d ", distance[n]);
			}
			printf("\n");
		}

		__delay32(1500000); // delay 0.05seconds
	}

	return 0;
}

//rotate through the four outputs connected to stepper motor
void step_forward()
{
	if (LATD == 0b0001) LATD = 0b0010;
	else if (LATD == 0b0010) LATD = 0b0100;
	else if (LATD == 0b0100) LATD = 0b1000;
	else LATD = 0b0001;
	step_counter++;
}

void step_back()
{
	if (LATD == 0b0001) LATD = 0b1000;
	else if (LATD == 0b0010) LATD = 0b0001;
	else if (LATD == 0b0100) LATD = 0b0010;
	else LATD = 0b0100;
	step_counter--;
}

//send a pulse to sensor and measure length of returning "echo" 
int get_distance()
{
	_LATF0=1;			// set RF0 high
	__delay32(3000); 	// wait 100 uS
	_LATF0=0;			// then set back low
	while (_RF1==0);	// wait to receive pulse from sensor
	TMR2=0;				// reset TMR2
	while (_RF1==1);	// time TMR2
	return TMR2;		// return value of TMR2
}

This is the Python code to plot the data using matplotlib:

import time
import serial
from pylab import *

# configure the serial connections
ser = serial.Serial(
    port='/dev/ttyUSB0',
    baudrate=38400,
   
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.SEVENBITS
)
ser.close()
ser.open()

# create an array of 800 numbers
distance = range(800); 

while True:
	line = ser.readline()
	values = line.split()
	for n in range(800):
		distance[n] = int(values[n])
	plot(distance)
	show()

Here are some pictres of the UltraSonic sensor mounted onto the stepper motor:

IMG_3411

IMG_3410

Here is a video of it in action:

I have discovered that this type of ultrasonic sensor has an effectual angle of 15° and a measuring angle of 30°, there for this will distort my plotted graph.
So I decided to try the Sharp IR distance sensor instead or the ultrasonic as I wouldn’t take much changing in the code nor the physical wiring.

So here is my new code for the Sharp IR distance sensor:


// Ultrasonic stepper-motor Radar Project
// Written by Aron Horan
// Last updated 21-11-2013
 
#include <xc.h>
#include <libpic30.h>
#include <stdio.h>
#include <math.h>
 
// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, Fcy=30MHz
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin
 
int step_counter = 0;
int angle = 0;
unsigned int read_analog_channel(int n);
void step_forward();
void step_back();

// create a 2D pixel array with 100 rows & 100 columns
int distance[800];

int main()
{
	int x, y, d, cm, state, reverse=0, forward=1, n;
	state = forward;

	// Configure UART
	U1BRG = 48;            // 38400 baud @ 30 MIPS
	U1MODEbits.UARTEN = 1; // Enable UART

	// Make all port D pins outputs
	TRISD = 0;
	// Make RF0 an output
	TRISF = 0b10;
	
	// Configure analog inputs
	TRISB = 0x01FF;      // Port B all inputs
	ADPCFG = 0xFF00;     // Lowest 8 PORTB pins are analog inputs
	ADCON1 = 0;          // Manually clear SAMP to end sampling, start conversion
	ADCON2 = 0;          // Voltage reference from AVDD and AVSS
	ADCON3 = 0x0005;     // Manual Sample, ADCS=5 -> Tad = 3*Tcy = 0.1us
	ADCON1bits.ADON = 1; // Turn ADC ON

	// Configure Timer 2
	T2CONbits.TCKPS = 0b10; // Timer 2 prescaler 1:64
	PR2 = 9375;             // Timer 2 period (20ms)
	T2CONbits.TON = 1;      // Enable Timer 2
	
	
	while(1)
	{
		d = read_analog_channel(0);
		distance[step_counter] = d;

		if(state == forward) // rotate clockwise until angle = 360 degrees
		{
			step_forward();
			if (step_counter == 799) state = reverse;
		}
		else if(state == reverse) // rotate anticlockwise until angle = 0
		{
			step_back();
			if (step_counter == 0) state = forward;
		}

		if (step_counter == 0 || step_counter == 799)
		{
			// Transmit all readings to PC
			for (n=0 ; n<800 ; ++n)
			{
				printf("%d ", distance[n]);
			}
			printf("\n");
		}

		__delay32(1000000); // delay 0.05/3seconds
	}

	return 0;
}

//rotate through the four outputs connected to stepper motor
void step_forward()
{
	if (LATD == 0b0001) LATD = 0b0010;
	else if (LATD == 0b0010) LATD = 0b0100;
	else if (LATD == 0b0100) LATD = 0b1000;
	else LATD = 0b0001;
	step_counter++;
}

void step_back()
{
	if (LATD == 0b0001) LATD = 0b1000;
	else if (LATD == 0b0010) LATD = 0b0001;
	else if (LATD == 0b0100) LATD = 0b0010;
	else LATD = 0b0100;
	step_counter--;
}

// This function reads a single sample from the specified
// analog input. It should take less than 2.5us if the chip
// is running at about 30 MIPS.
unsigned int read_analog_channel(int channel)
{
	ADCHS = channel;          // Select the requested channel
	ADCON1bits.SAMP = 1;      // start sampling
	__delay32(30);            // 1us delay @ 30 MIPS
	ADCON1bits.SAMP = 0;      // start Converting
	while (!ADCON1bits.DONE); // Should take 12 * Tad = 1.2us
	return ADCBUF0;
}

Here are some pictures of the Sharp IR sensor mounted on the stepper motor:

IMG_3412

IMG_3414

Advertisements

7 thoughts on “2D Plotter

  1. Excellent project! It’s a pity about the sensing angle of the ultrasonic, but let’s just chalk that up to experience. The system is working really well within the limits of the sensor. Good video too – it really explains how the whole thing works.

    Ted

  2. Pingback: Measuring distance using a webcam and a laser | shaneormonde

  3. I notice you are mounting both sensors horizontally (as pretty much everyone else on the internet it seems). According to the datasheet of the Sharp sensor it would be able to detect edges more sharply if mounted vertically. Maybe the ultrasonic sensor works the same. Accoustics probably work differently but worth a try. At least with the Sharp sensor.

    • I assumed with the convex lens on the Sharp IR that it wouldn’t make a difference. It has me thinking now.
      I’ll give it a shot and let you know.
      Thank a for the input, much appreciated

  4. I have some questions. I just started to learn robotics. can we use 2 different ranges of IR sensors for map building? (GP2Y0D02YK and GP2Y0A700k) because of first one have a max range of 59.5 inches and 2nd one have 216.5 inches but the latter one can’t give correct reading if an object is placed near than 40 inches. so can i overwrite the lower values from the 2nd one to the first one?? and how?

    • Sorry Hudaib, my reply seems to have been scrambled possible as I was on my phone.

      What I meant to say:

      Read short IR sensor values;
      Read long IR sensor values;

      if (short IR values || long IR values) are less than 40)
      {
      distance = readings from short IR sensor;
      }

      else
      {
      distance = readings from long IR sensor;
      }

      There is a possibility that the readings from an out of range sensor might cause problems in which I think there is a simple solution, but try this first. Please let me know how you get on.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s