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