Bluetooth Controlled Car

In this project I plan to control a robot via bluetooth using a serial bluetooth module the hc-05.
I firstly wanted to get familiar with changing the state of the robot with a hard wired serial to USB device. I built a simple circuit with three LED’s and code that has three different states; one state for each LED to be turned on, then a python script to send different characters via a USB to serial port.

Here is a circuit diagram of the system:

LEDserial

Here is a picture of the circuit:

IMG_3431

IMG_3429

Here is my code:


//
// Testing serial control with USB serial to dsPIC30F4011
// Written by Aron Horan
// 10 Dec 2013
//
 
#include <xc.h>
#include <libpic30.h>
 
// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, i.e. 30 MIPS
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin

 
int main(void)
{
	int state = 0;
    char g, h, j, c; 
 
    TRISB = 0;
    
    // Configure UART
	U1BRG = 48;            // 38400 baud @ 30 MIPS
	U1MODEbits.UARTEN = 1; // Enable UART
	

	while(1)
	{
		// Check if any characters were received via UART
        if (U1STAbits.URXDA == 1)     
        {
            // Check that first character was 'f,g or h'
            c = U1RXREG;
            if (c == 'g') state = 1;
            else if (c == 'h') state = 2;
            else if (c == 'j') state = 3;
        }

		//LED on RD0
		if (state == 1) 
		{
			LATB = 0b001;
		}
		
		//LED on RD1
		if (state == 2)
		{
			LATB = 0b010;
		}
		
		//LED on RD2
		if (state == 3)
		{
			LATB = 0b100;
		}
	}
	return 0;
}

I firstly wanted to setup the python to send a char every three seconds, after I get that going I will change it so that it will take inputs from my keyboard.
I also am using a USB to serial port for the moment, once I get that up and running I will setup the bluetooth serial port and control remotely.

Here is my python code that sends a different char every three seconds:


import time
import serial

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

	print "g"
	ser.write("g")
	time.sleep(3)
	
	print "h"
	ser.write("h")
	time.sleep(3)
	
	print "j"
	ser.write("j")
	time.sleep(3)


Here is a video of it in action:

Now that I have that working I have edited the python script to recieve inputs from the keyboard to change state.

Here is the new python code:


import time
import serial

# configure the serial connections (the parameters differs on the device you are connecting to)
ser = serial.Serial(
    port='/dev/ttyUSB0',
    baudrate=38400,
   
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS
)
ser.close()
ser.open()
	
while True:

#print 'Enter your commands below.\r\nInsert "exit" to leave the application.'
	
	# get keyboard input
	input = raw_input(">> ")
        # Python 3 users
        # input = input(">> ")
	if input == 'exit':
		ser.close()
		exit()
	else:
		# send the character to the device
		# (note that I happend a \r\n carriage return and line feed to the 			characters - this is requested by my device)
		ser.write(input + '\r\n')
		out = ''
		
		# wait half a second before reading output (give device time 			 	     # to answer)
		time.sleep(0.5)
		while ser.inWaiting() > 0:
			out += ser.read(1)
			
		if out != '':
			print ">>" + out

The only thing is the I must press enter (return) for the char to be sent. My next stage I will overcome this problem. Also instead of using the USB to serial port I will be using a serial Bluetooth device so I can transmit wirelessly.

So I finally got it working.

Its wirelessly switching a few LEDs (wow!) but now I have the power to do a lot more with it.

I ended up using Tkinter to create a canvas with 3 buttons. Each button sends a different character to the PIC, changing it between three different states.

My C programm is exactly the same as above the only difference is the python script.

Here is my Python script:


import time
import serial
import Tkinter
 
# Define a keyboard callback function. This will be called
# every time a key is pressed anywhere in the window.
def key(event):
    print "Sending", repr(event.char)
    ser.write(event.char)
 
# Callback function for the 'A' button
def a_press():
    print "Sending 'g'"
    ser.write('g')
 
# Callback function for the 'B' button
def b_press():
    print "Sending 'h'"
    ser.write('h')
 
# Callback function for the 'C' button
def c_press():
    print "Sending 'j'"
    ser.write('j')
 
# Open first serial port
ser = serial.Serial(port='/dev/rfcomm0', baudrate = 9600, timeout=1)
 
# Create a Tk GUI window
root = Tkinter.Tk()

# create canvas with a width and height
Tkinter.Canvas(root, width=600, height=600)

# Add title to window
root.title("ARONS BLUETOOTH RC CAR")
 
# Bind all keypresses to the "key" function (define above)
root.bind("<Key>", key)
 
# Create a few buttons and connect each one to a function
a = Tkinter.Button(root, text='A', command=a_press)
b = Tkinter.Button(root, text='B', command=b_press)
c = Tkinter.Button(root, text='C', command=c_press)
 
# Lay out buttons in the GUI
a.grid(row=0, column=0, sticky='EW')
b.grid(row=1, column=0, sticky='EW')
c.grid(row=2, column=0, sticky='EW')
root.columnconfigure(0, weight=1)
 
# Enter the Tkinter main event loop. The program will stay
# in this event loop until it's time to exit.
root.mainloop()
 
# Close serial port
ser.close()
	

Here is a video of it in action:

Having awful trouble with my bluetooth device, possible blew it somehow 😦 gonna order a new one and will get back to this project when it arrives.

Advertisements

The Dodging Robot

IMG_3562

In this Project I plan on remotely controlling a two-wheeled car I built via bluetooth.In this project I wanted to make a small two wheeled robot that drives around dodging evrything infront of it.
I mounted two SHARP IR Distance sensors to the front so that the robot can decide which way to turn if an object triggers either sensor.

I used an 18 pin dsPIC30F3012 for this as I wanted to fit the dsPIC and driver chip SN754410NE onto one small breadboard, also the dsPIC30F3012 had all the io I needed.

I used state’s for each circumstance the robot can be in, in each state there are conditions that if occur the program will change to a different state.

The states of the code go as follows:

StateMachineTable

The output voltage of the infrared sensor was then measured at different distances so that I could decide at what distance I wanted it to turn.
The results were as follows:

Capture

Plotted on a graph it looked like this:

Capture1

Here is a wiring diaram of the circuit:

rect4922

Here is my code:


// dsPIC30F3012
// The dodgy Robot
// Written by Aron Horan
// The plan of this project is to make a two wheeled robot with two IR sensors
// mounted to the front. The robot will simply drive around dodging objects.
// If the two sensors have a low reading the robot will drive straight,
// if the left sensror goes high and right is low the robot turns right and vise versa,
// if either sensor goes very high the robot will reverse for a second and turn around

#include <xc.h>
#include <stdio.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

// Function prototypes
unsigned int read_analog_channel(int);

int main()
{
	const turn_right = 0, turn_left = 1, forward = 2, turn_around = 3;
	int state = forward;
	int left_eye;
	int right_eye;
	int sw = 0;
	
	// Configure UART
	U1BRG = 48;            // 38400 baud @ 30 MIPS
	U1MODEbits.UARTEN = 1; // Enable UART
	

	// Make RB0-3 outputs
	TRISB = 0b1111111111110000;

	// Configure analog inputs
	ADPCFG = 0b1111111100111111;// Only AN6 and AN7 are analog inputs
	ADCON1 = 0;                 // Manually clear SAMP to end sampling, start conversion
	ADCON2 = 0;                 // Voltage reference from AVDD and AVSS
	ADCON3 = 19;            	// Manual Sample, ADCS=9 -> Tad = 10*Tcy = 333ns
	ADCON1bits.ADON = 1;        // Turn ADC ON

	
	while(1)
	{
		left_eye = read_analog_channel(6); 	// read infrared detector
		right_eye = read_analog_channel(7); // read infrared detector
	
	   
       if (state == forward)
       {
            LATB = 0b1010; // motors: left forward, right forward
            if (left_eye > 900 && right_eye < 900) state = turn_right;
            if (left_eye < 900 && right_eye > 900) state = turn_left;
            if (left_eye > 2200 || right_eye > 2200) state = turn_around;
       }
       
       else if (state == turn_right)
       {
              LATB = 0b1000; // motors: left stop, right forward
              if (left_eye < 900 && right_eye < 900) state = forward;
              if (left_eye > 2200 || right_eye > 2200) state = turn_around;
       }
       
       else if (state == turn_left)
       {
            LATB = 0b0010; // motors: left forward, right stop
            if (left_eye < 900 && right_eye < 900) state = forward;
            if (left_eye > 2200 || right_eye > 2200) state = turn_around;
       }
       else if (state == turn_around)
       {
            LATB = 0b0101; // motors: left reverse, right reverse
            __delay32(40000000);
            LATB = 0b0110; // motors: left reverse, right reverse
            __delay32(30000000);
            state = forward;
       }
       	    __delay32(300000);
	}
	return 0;
}

// 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 finished piece:

IMG_3402

IMG_3403

IMG_3404

IMG_3406

IMG_3407

I will have a video of it in action very shortly, im just low on batteries at the moment and can only run it while plugged in, which wouldn’t make a good video…

Had a bit of a disaster with this little poor fellow. Afer driving from Greystones to Dublin on my bike I Arrived into college to find my bag zip open… Dodgbot was gone…

So without further wait I bring to you…..

DODGBOT V2.0IMG_3554IMG_3556

IMG_3558

IMG_3560

IMG_3562

IMG_3554

I ended up having to buy a set of AA NI-MH rechargable batteries as it kept resetting when the motors switched into reverse due to the curent surge and voltdrop.

Still even with these new 1700mAH batteries it was still resetting, so I ended up using a heap of capacitors (2160uF) is was done the trick.

So finally here is a video of it in action: