Help Needed: Controlling a motor using ultrasonic sensor and IR sensor

RobotHeart

Joined Feb 21, 2010
30
Hello everyone

I'm actually a new member here as i wish i can get the help i need, and also try to help others.
I'm doing my final year project which is an assistance aid that helps blind people avoid obstacles while walking.

in this topic i want to seek help while im doing my software part.
at the FIRST part...What im going to do is that i want to control a vibration motor (rotation in 1 direction only) depending on the output of ultrasonic sensor which is Maxbotix EZ1 (datasheet : http://www.maxbotix.com/uploads/LV-MaxSonar-EZ1-Datasheet.pdf )
this sensor got digital output (PWM), and an input of 5V with a detection distance that can reach to 6m. in this project im going to use the PWM output.

the process will be:
- if there is a far obstacle the vibration motor should rotate slowly.
- if there is a medium distance obstacle the vibration motor should rotate at normal speed.
- if there is a near obstacle the vibration motor should rotate fast.

Im going to use PIC16F876A microcontroller which has an internal ADC and other sufficient features.
there is no display LCD or buzzers...no..just as simple as that (thats for FIRST part) and as im pretty weak in programming , i'll need your full help.

at start i want to control the ultrasonic sensor...i've found a source code in the Maxbotix supplier (Cytron) forums, the code does control the ultrasonic, but for different output purposes which can be adjusted easily.
Rich (BB code):
//============================================================================
//   Include
//============================================================================
#include <pic.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "delay.h"
#include "delay.c"
//============================================================================
//   Configuration
//============================================================================
__CONFIG ( 0x3F32 );
//============================================================================
//   Function Prototype
//============================================================================
void ultrasonic(void);   // Find range based on input
void init(void);
void rangecal(void);
//============================================================================
//   global variable
unsigned int To=0;
unsigned int TH=0;
unsigned int value;
unsigned int distance;
unsigned int data=0;

//============================================================================
//   interrupt prototype
//============================================================================================================
static void interrupt isr(void)
{
if(TMR0IF)         // TMR0 is overflow
{
TMR0IF=0;    // clear flag bit
To+=0x100;      // count number of TMR0 overflow ( make it to 16bit TMR)
}
}
//============================================================================
//   Main Function
//============================================================================
void main(void)
{
init();
ultrasonic();
}

// Initailization
// Description : Initialize the microcontroller
//============================================================================================================

void init()
{
// Tris configuration (input or output)
TRISA = 0b00000000;      //set PORTA as output
TRISB = 0b00000100;      //set RB2 pin as input, other as output
TRISC = 0b00000000;      //set PORTA as output

RB4=1;   //5V to sensor
DelayMs(250);  //sensor module power up time

// TMR 0 configuation
T0CS=0;
PSA=0;
PS2=1;                  // prescale 1:256
PS1=1;                  //
PS0=1;                  //
TMR0IE=1;                  // TMR0 Interrupt
TMR0=0;

GIE = 1;   //global interrupt
}
//================================================================================
// FUNCTIONS
//================================================================================
//**************************************************
//Calculate the range from the sensor depending on PWM signal input
void ultrasonic(void)
{
while(1)
{
if(RB2==0)               //if RB2 is high
{
TMR0=0;            // clear all counter involved, start new count for period of RB2 high
To=0;
}
else
{
TH=TMR0+To;         // RB2 is 0 mean is falling from 1 save TH, RB2 high period
value=TH;      //value of tmr0+to
distance=value*1.75616;   // calculate inch value per inch = 147us with 20Mhz internal clock.
rangecal();
}
}

}

void rangecal(void)
{

if(distance>100)
{
PORTC=0B00000001;
}
else if(distance>80)
{
PORTC=0B00000010;
}
else if(distance>60)
{
PORTC=0B00000100;
}
else if(distance>40)
{
PORTC=0B00001000;
}
else if(distance>20)
{
PORTC=0B00010000;
}
}
for this code, the user used PIC16F877 (which has an internal OSC)

at first, i tried compiling the code just for checking but the following errors occurred:

can't open include file #include <pic.h>
can't open include file #include <stdlib.h>
can't open include file #include <string.h>
can't open include file #include <stdio.h>
can't open include file #include "delay.h"
can't open include file #include "delay.c"

the compiler that im using is MikroC PRO (& MikroC)....i think there are some missing files if im not mistaken, i tried simply to delete those lines but of course 10s of errors occured.

any idea what should i do to compile this code successfully ?

i need some attention for this topic please as this is my final year project.

thank you

BMorse

Joined Sep 26, 2009
2,675

RobotHeart

Joined Feb 21, 2010
30
well that project can be useful in developing my project after finishing mine, specially that i don't like taking others 'exact' job...have to put my own touch
thanks alot

BMorse

Joined Sep 26, 2009
2,675
well, it is just a "guide" on how you can accomplish certain tasks for your project....

B. Morse

RobotHeart

Joined Feb 21, 2010
30
for the previous problem i had to use HI-TECH C-Compiler and also delete the delay lines (although i got the delay.h file but still wont work ! ). maybe i'll have to do some empty loops if i want to do delay later on !

anyway...my problem now is that i want to convert the analog voltage coming from the IR sensor to digital and then back to analog again by using PIC16F877A.

the following code convert from analog to digital:

Rich (BB code):
   #include <built_in.h>

void main() {
ANSEL  = 0x04;              // Configure AN2 pin as analog
TRISA  = 0xFF;              // PORTA is input
ANSELH = 0;                 // Configure other AN pins as digital I/O
TRISC  = 0x3F;              // Pins RC7, RC6 are outputs
TRISB  = 0;                 // PORTB is output

do {
PORTB = temp_res;         // Send lower 8 bits to PORTB
PORTC = temp_res >> 2;    // Send 2 most significant bits to RC7, RC6
} while(1);
}

the previous code convert the analog voltage and send it to portB and portC as a binary number...lets say we have an input of 1V >> 1V/.00489 >> 205 decimal = 11001101 in binary.

now i don't want the binary output as the final result...i want to get an analog output from 1 pin.
lets say the input coming from IR sensor and going to microcontroller is as following:
0.5V, 1V, 1.5V, 2V, 2.5V, 3V

the conversion needed from input to the final output is as following

note that the output values at the right side are supposed to be analog.

so the question is, what is the code modification needed to get analog values instead of the binary output given by ADC ?

i tried my best to make it as clear as possible, now i need your help

thank you

Markd77

Joined Sep 7, 2009
2,806
For motor control the PWM output of the PIC would be best. It's not strictly analog but it is excellent for motor control.
Your input output chart isn't exactly linear. I'm not sure if you just want these 6 values with a step change in between. If you do then a lookup table would be fine.
If you want a smooth response a linear relationship would be easier and close enough.
Your input has a 2.5V range and the output range is 5V so you would just subtract the input from 3V and multiply by 2.
It will have to be scaled to match the range of your ADC and the PWM generator but that should be easy enough.

RobotHeart

Joined Feb 21, 2010
30
well i did mention that im weak in programming ....thats why i choosed the input values i've wrote previously...but if the linear relationship is easy enough for a newbie, it will be great !
so as u said, in my case i have to substract the input from 3V and then multiply by 2

lets say:

Rich (BB code):
output_value = ( temp_res - 3 )* 2

PortB.2 = output_value
is that somehow partialy correct ?

please guide me to write this code as i really need to come up with something that works properly.

thank you

Markd77

Joined Sep 7, 2009
2,806
Not quite:

Just using the high byte of the left shifted ADC result, 3V would be (3/5)*255=153

output_value = ( 153-temp_res )* 2

This will give you a value of 0-255 which you will have to send to the PWM peripheral. I don't really understand C so you would have to find some example. I'm sure there are plenty out there.
I'm also not sure if in C the above line uses only the higher byte of temp_res, if someone could check....

Last edited:

symqwerty

Joined Feb 22, 2010
31
Hello everyone

I'm actually a new member here as i wish i can get the help i need, and also try to help others.
I'm doing my final year project which is an assistance aid that helps blind people avoid obstacles while walking.

in this topic i want to seek help while im doing my software part.
at the FIRST part...What im going to do is that i want to control a vibration motor (rotation in 1 direction only) depending on the output of ultrasonic sensor which is Maxbotix EZ1 (datasheet : http://www.maxbotix.com/uploads/LV-MaxSonar-EZ1-Datasheet.pdf )
this sensor got digital output (PWM), and an input of 5V with a detection distance that can reach to 6m. in this project im going to use the PWM output.

the process will be:
- if there is a far obstacle the vibration motor should rotate slowly.
- if there is a medium distance obstacle the vibration motor should rotate at normal speed.
- if there is a near obstacle the vibration motor should rotate fast.

Im going to use PIC16F876A microcontroller which has an internal ADC and other sufficient features.
there is no display LCD or buzzers...no..just as simple as that (thats for FIRST part) and as im pretty weak in programming , i'll need your full help.

at start i want to control the ultrasonic sensor...i've found a source code in the Maxbotix supplier (Cytron) forums, the code does control the ultrasonic, but for different output purposes which can be adjusted easily.
Rich (BB code):
//============================================================================
//   Include
//============================================================================
#include <pic.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "delay.h"
#include "delay.c"
//============================================================================
//   Configuration
//============================================================================
__CONFIG ( 0x3F32 );
//============================================================================
//   Function Prototype
//============================================================================
void ultrasonic(void);   // Find range based on input
void init(void);
void rangecal(void);
//============================================================================
//   global variable
unsigned int To=0;
unsigned int TH=0;
unsigned int value;
unsigned int distance;
unsigned int data=0;

//============================================================================
//   interrupt prototype
//============================================================================================================
static void interrupt isr(void)
{
if(TMR0IF)         // TMR0 is overflow
{
TMR0IF=0;    // clear flag bit
To+=0x100;      // count number of TMR0 overflow ( make it to 16bit TMR)
}
}
//============================================================================
//   Main Function
//============================================================================
void main(void)
{
init();
ultrasonic();
}

// Initailization
// Description : Initialize the microcontroller
//============================================================================================================

void init()
{
// Tris configuration (input or output)
TRISA = 0b00000000;      //set PORTA as output
TRISB = 0b00000100;      //set RB2 pin as input, other as output
TRISC = 0b00000000;      //set PORTA as output

RB4=1;   //5V to sensor
DelayMs(250);  //sensor module power up time

// TMR 0 configuation
T0CS=0;
PSA=0;
PS2=1;                  // prescale 1:256
PS1=1;                  //
PS0=1;                  //
TMR0IE=1;                  // TMR0 Interrupt
TMR0=0;

GIE = 1;   //global interrupt
}
//================================================================================
// FUNCTIONS
//================================================================================
//**************************************************
//Calculate the range from the sensor depending on PWM signal input
void ultrasonic(void)
{
while(1)
{
if(RB2==0)               //if RB2 is high
{
TMR0=0;            // clear all counter involved, start new count for period of RB2 high
To=0;
}
else
{
TH=TMR0+To;         // RB2 is 0 mean is falling from 1 save TH, RB2 high period
value=TH;      //value of tmr0+to
distance=value*1.75616;   // calculate inch value per inch = 147us with 20Mhz internal clock.
rangecal();
}
}

}

void rangecal(void)
{

if(distance>100)
{
PORTC=0B00000001;
}
else if(distance>80)
{
PORTC=0B00000010;
}
else if(distance>60)
{
PORTC=0B00000100;
}
else if(distance>40)
{
PORTC=0B00001000;
}
else if(distance>20)
{
PORTC=0B00010000;
}
}
for this code, the user used PIC16F877 (which has an internal OSC)

at first, i tried compiling the code just for checking but the following errors occurred:

can't open include file #include <pic.h>
can't open include file #include <stdlib.h>
can't open include file #include <string.h>
can't open include file #include <stdio.h>
can't open include file #include "delay.h"
can't open include file #include "delay.c"

the compiler that im using is MikroC PRO (& MikroC)....i think there are some missing files if im not mistaken, i tried simply to delete those lines but of course 10s of errors occured.

any idea what should i do to compile this code successfully ?

i need some attention for this topic please as this is my final year project.

thank you
first of all, I believe that pic16f877 DONT have internal oscillator...

if you want to use some C function like above, you MUST make sure that *.h file EXIST.(when compiling, compiler will look for THAT files)
OR
MikroC have tons of built-in functions such as 'delay' and etc. So, you dont have to include that header file.

Bear in mind that you are programming MCU in C environment. Dont expect to have full function/features like what has been defined in ANSI C. Read MikroC manual regarding ANSI C support.

For the sensor, i recommend you to use CCP module(plus interrupt) in order to read PWM signal.
OR
you can use analog as an input instead of pulse since you have 3 options the read the output from the sensor. Anyway, choose what you like

For ADC part(your IR sensors), you must set the Vref. Are you sure that your IR sensor will output max 5V analog?By default, the Vref tied to Vcc of the MCU( i assume that you know abt this ). Then, after get the digital val, you can do the math to manipulate the readings.

RobotHeart

Joined Feb 21, 2010
30
Not quite:

Just using the high byte of the left shifted ADC result, 3V would be (3/5)*255=153

output_value = ( 153-temp_res )* 2

This will give you a value of 0-255 which you will have to send to the PWM peripheral. I don't really understand C so you would have to find some example. I'm sure there are plenty out there.
I'm also not sure if in C the above line uses only the higher byte of temp_res, if someone could check....
so ur saying the equation:
output_value = ( 153-temp_res )* 2
will get the value that will be sent to the output port ?
but why it is sent to the PWM ? i need an analog output...i mean PWM gives a pulse as i know so far, so how can i control a motor by a pulse that doesn't change in amplitude ? i know there's something here im missing..hope u tell me what it is
tq

RobotHeart

Joined Feb 21, 2010
30
first of all, I believe that pic16f877 DONT have internal oscillator...

if you want to use some C function like above, you MUST make sure that *.h file EXIST.(when compiling, compiler will look for THAT files)
OR
MikroC have tons of built-in functions such as 'delay' and etc. So, you dont have to include that header file.

Bear in mind that you are programming MCU in C environment. Dont expect to have full function/features like what has been defined in ANSI C. Read MikroC manual regarding ANSI C support.

For the sensor, i recommend you to use CCP module(plus interrupt) in order to read PWM signal.
OR
you can use analog as an input instead of pulse since you have 3 options the read the output from the sensor. Anyway, choose what you like

For ADC part(your IR sensors), you must set the Vref. Are you sure that your IR sensor will output max 5V analog?By default, the Vref tied to Vcc of the MCU( i assume that you know abt this ). Then, after get the digital val, you can do the math to manipulate the readings.
- ya i knew that and used an external 20MHZ oscillator
- ya i also tried that, someone gave me the delay file (delay.h)...ried to past is into the MikroC system file called Include which include all the libraries...didn't work for the delay file...but worked for other !
- about the ultrasonic sensor...i've uploaded the previous software and been able to calculate the distance using the PWM...but still couldn't send the result to a single output pin to have an analog "linear" output...instead...various pins were toggled to represent the output as shown on the last lines of the previous code.
- the IR maximum output that goes to MCU is 3V....does that mean the Vref should be changed to 3V ??
tq

symqwerty

Joined Feb 22, 2010
31
- ya i knew that and used an external 20MHZ oscillator
- ya i also tried that, someone gave me the delay file (delay.h)...ried to past is into the MikroC system file called Include which include all the libraries...didn't work for the delay file...but worked for other !
- about the ultrasonic sensor...i've uploaded the previous software and been able to calculate the distance using the PWM...but still couldn't send the result to a single output pin to have an analog "linear" output...instead...various pins were toggled to represent the output as shown on the last lines of the previous code.
- the IR maximum output that goes to MCU is 3V....does that mean the Vref should be changed to 3V ??
tq
I think your method should be revised. You want to output the reading in analog form, right? There are 3 ways to implement it.

1. Since you have "digital" value after you, what you could do is to buy an DAC chip..pass all the 8bit or 10-bit value to DAC to convert it to analog. There are 2 type of DAC IC, parallel or serial input. Parallel input means that single pin represent single bit.Thus, if you have 10 bit value, it is equal to 10 pin must be connected to the chip(each way). The
serial require one pin only but you must know how to use SPI or I2C

2. Using PWM..You can generate analog output using PWM. The method is the same as before but instead of reading, you generate the PWM based on the reading you have. It's something like a 'low-cost' DAC.

3. The simplest method. The sonar sensor itself has 3 types of output, uart, analog(this is what u want) and pulse(PWM). Why dont you just take the output from the sensor(it's in analog form).

May i ask you a question? Why you want to convert it to analog form?

For ADC portion, Vref will affect your ADC sensitivity. Why? If you maximum input is 3V, but your Vref tied to 5V, then,

1-bit = 5/(2^10)V = 4.88mV >>>> maximum digital val @3V = 614.4 or 614

but if Vref=3.0

1-bit = 3/(2^10)V = 2.93mV >>>> max dig val @3 = 1024 = 2^10

RobotHeart

Joined Feb 21, 2010
30
first of all...i think i should've explained how my sensors work and what types do i have.
i have 3 types of sensors with a total number of 5 sensors:

1\ EZ1 maxbotix Ultrasonic sensor:
- used to detect objects on the front side of the device.
- input voltage: 5V
- output voltage: analog, PWM (digital), etc
- analog output voltage range: 0V to 5V
- range of detection: 6m
- the required range in my project: 2m
- the relationship between analog output voltage and distance: proportional (means when the distance of the obstacle increase the voltage increase too)
- the output used to be connected to MCU: PWM (digital).

2\ Standard Ultrasonic sensor module (quantity = 2)
- used to detect objects on left and right sides.
- input voltage = 5V
- output voltage: Analog only
- analog output voltage range: 0V to 4.5V
- range of detection: 3m
- the required range in my project: 1 to 1.5m
- the relationship between analog output voltage and distance: proportional (means when the distance of the obstacle increase the voltage increase too, the required relation is the opposite...thats why im using a MCU to give the reverse output )
- the relationship between digital output and distance: the PWM width increase when the object goes far...but after using the distance equation the relationship becomes non-proportional (voltage increase when object come closer).
- the output used to be connected to MCU: Analog.

3\ SHARP IR sensor (quantity = 2)
- used to detect holes and low objects .
- input voltage = 5V
- output voltage: Analog only
- analog output voltage range: 0V to 3V (can be amplified to 5V)
- range of detection: 1m
- the required range in my project: 10cm to 1m
- the relationship between analog output voltage and distance: non-proportional ( means when the object comes near...the output voltage increases, so one of the 2 sensors will be directly connected to the motor, the other sensor (hole detection) will be connected through MCU to get the reveres relation).
- the output used to be connected to MCU: Analog.

so....all of the sensor (except for the hole detection sensor) will be connected to the MCU...and all of those which r connected to the MCU (except the EZ1 maxbotix Ultrasonic sensor) will have a reveres relation in order to make the motors rotate faster when the obstacles come nearer.

1. Since you have "digital" value after you, what you could do is to buy an DAC chip..pass all the 8bit or 10-bit value to DAC to convert it to analog. There are 2 type of DAC IC, parallel or serial input. Parallel input means that single pin represent single bit.Thus, if you have 10 bit value, it is equal to 10 pin must be connected to the chip(each way). The
serial require one pin only but you must know how to use SPI or I2C

2. Using PWM..You can generate analog output using PWM. The method is the same as before but instead of reading, you generate the PWM based on the reading you have. It's something like a 'low-cost' DAC.

3. The simplest method. The sonar sensor itself has 3 types of output, uart, analog(this is what u want) and pulse(PWM). Why dont you just take the output from the sensor(it's in analog form).

May i ask you a question? Why you want to convert it to analog form?

For ADC portion, Vref will affect your ADC sensitivity. Why? If you maximum input is 3V, but your Vref tied to 5V, then,

1-bit = 5/(2^10)V = 4.88mV >>>> maximum digital val @3V = 614.4 or 614

but if Vref=3.0

1-bit = 3/(2^10)V = 2.93mV >>>> max dig val @3 = 1024 = 2^10
1\ using DAC will be a good idea...but only for the EZ1 maxbotix ultrasonic sensor since its the only one having (connected to MCU) a non-proportional relation.

2\ i think using the PWM is the best way...although im not good in programming...but i trust you guyz on teaching me how to do it

3\ well...i have a small problem trying to make a conclusion from the calculation u have just made
Rich (BB code):
1-bit = 5/(2^10)V = 4.88mV >>>> maximum digital val @3V =  614.4 or 614

but if Vref=3.0

1-bit = 3/(2^10)V = 2.93mV  >>>> max dig val @3 = 1024 =  2^10
but i think i should amplify the 3V to 5V (coming from the IR sensor to the MCU) in order for all sensors to have the same Vref without complications.

im very sorry for the long explanation

RobotHeart

Joined Feb 21, 2010
30
waiting for replies...help is really needed !

symqwerty

Joined Feb 22, 2010
31
Yup, you could do it either way..using opamp would help you w/o affecting Vref.

It's hard to discuss about generating analog from PWM w/o diagram here but i have some article for you..

The basic idea is:

Let's assume that you have a pwm signal(with FIXED period) @50Hz

so, the period is 1/50Hz = 20ms

Logic high = VCC / 5V
logic Low = GND

at DC=100%; Vo = 5v
at DC=50%; Vo = 2.5v
at DC=10%; Vo = 0.5V

or (Vlogic/100)*DC or (Vcc/period)*(time@logic high)

*remember, pwm freq will affect the output

RobotHeart

Joined Feb 21, 2010
30
thank you for replying...almost lost hope
So basically the PWM will be converted to analog signal using a LP filter...ok first of all..im using PIC16F877A...does it have a PWM output pin ? which one is it ? is it the CCP1 and CCP2 ??

and what is the code that can be used to apply the equations u mentioned and do i still have to apply the equations mentioned in previous replies (output_value = ( 153-temp_res )* 2 ) ?

i need an explanation in terms of steps if possible, because things are getting slightly mixed up here

p.s. always note that there are outputs that have proportional relation with the input, and outputs that have a non-proportional relation with the input, so i guess 2 different types of equations are needed in my case.

symqwerty

Joined Feb 22, 2010
31
It's up to you either to use CCP1 or CCP2..That PIC have 2 PWM output.

RobotHeart

Joined Feb 21, 2010
30
can you show me what are the steps on using CCP1 for example ?

aneeshmp200745

Joined Feb 24, 2010
9