CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

2 general questions about using a PIC processor
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
elasticman



Joined: 26 May 2009
Posts: 8

View user's profile Send private message

2 general questions about using a PIC processor
PostPosted: Tue May 26, 2009 12:17 pm     Reply with quote

Hello all, I'm pretty new to all of this so I hope my questions don't sound too stupid:)

I'm working on my final project for my first degree in mechanical engineering and I have designed and built a robot.
I'm going to mount IR sensors to it and am using the PIC18F4431.

I wanted to make sure of one thing first : when I want the PIC to operate the motors (I'm using 3 DC gear motors) in accordance to the voltage thats coming from the IR sensors do I control the VOLTAGE to the motors via the programming or is it done by the electronics (the driver)??

And second : what type of data do I get from the A/D converter - analog data gets in and digital data gets out. But what exactly do I get? a number? or what exactly??

thank you very much in advance
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 26, 2009 1:03 pm     Reply with quote

If you bought the board with the IR sensors and motor driver on it,
post a link to the webpage for the board. If you're building it yourself
then post the manufacturer and part numbers of the IR sensors and
motor driver components. Also post links to the data sheets.

The A/D converter will return a number from 0 to 255. This number
corresponds in a linear manner to the input voltage at the A/D pin. For a
PIC running at +5v, the input voltage can be from 0 to +5v, and the
output of the A/D will be 0 to 255.

The A/D can also run in 10-bit mode, in which case the output values
will be 0-1023 over the 0-5v input voltage range.
elasticman



Joined: 26 May 2009
Posts: 8

View user's profile Send private message

PostPosted: Tue May 26, 2009 2:01 pm     Reply with quote

PCM programmer wrote:
If you bought the board with the IR sensors and motor driver on it,
post a link to the webpage for the board. If you're building it yourself
then post the manufacturer and part numbers of the IR sensors and
motor driver components. Also post links to the data sheets.

The A/D converter will return a number from 0 to 255. This number
corresponds in a linear manner to the input voltage at the A/D pin. For a
PIC running at +5v, the input voltage can be from 0 to +5v, and the
output of the A/D will be 0 to 255.

The A/D can also run in 10-bit mode, in which case the output values
will be 0-1023 over the 0-5v input voltage range.


thank you
i bought the PIC and im using it in an OLIMEX PIC-P40-USB
i don't know which drivers yet (that is something that im going to get tomorrow from the electrician in the lab)
where can i find the exact linearity of the output values and the corresponding voltage?
also,if i understand correctly , i use control the motors through my programming as in , i either tell it to send a pulse or not (on or off) and then the driver takes care of the voltage to the motor....is that true? (isnt it a global thing with drivers?)
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 26, 2009 2:04 pm     Reply with quote

Here is a test program that will read the incoming voltage and convert
the ADC value to a voltage which can be displayed.
http://www.ccsinfo.com/forum/viewtopic.php?t=32168&start=1
Note that Ttelmah says the actual divisor should be 1024.

Look on page 16 of the A/D Reference manual for the transfer function:
http://ww1.microchip.com/downloads/en/DeviceDoc/31023a.pdf
elasticman



Joined: 26 May 2009
Posts: 8

View user's profile Send private message

PostPosted: Thu May 28, 2009 12:28 am     Reply with quote

Thank you PCM programmer.

I wanna make sure I get something, if I have 3 IR sensors, I connect them to AN0, AN1, AN2...
then I have my pic do the A/D conversion on the AN0, delay then read, convert AN1, delay then read, convert AN3 , delay then read.

Right?
and I'm going to use a 20 microsecond delay for each read (my OLIMEX board has a 20MHz clock).
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Thu May 28, 2009 8:04 am     Reply with quote

You want to

1) select AN0
2) delay
3) convert AN0
4) select AN1
5) delay
6) convert AN1
7) select AN2
8) delay
9) convert AN2

The delay needs to be between switching the A/D mux and running the conversion.
_________________
The search for better is endless. Instead simply find very good and get the job done.
elasticman



Joined: 26 May 2009
Posts: 8

View user's profile Send private message

PostPosted: Thu May 28, 2009 8:12 am     Reply with quote

SherpaDoug wrote:
You want to

1) select AN0
2) delay
3) convert AN0
4) select AN1
5) delay
6) convert AN1
7) select AN2
8) delay
9) convert AN2

The delay needs to be between switching the A/D mux and running the conversion.


Something like this :
Code:
 
set_adc_channel(front_sensor);
delay_us(20);
data_from_front_sensor = READ_ADC();

set_adc_channel(right_sensor);
delay_us(20);
data_from_right_sensor = READ_ADC();

set_adc_channel(left_sensor);
delay_us(20);
data_from_left_sensor = READ_ADC();

???
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Thu May 28, 2009 12:31 pm     Reply with quote

Yes, that is the sequence. I would have to look at your chip to see if 20us is the right time length. Usually I do math and storage on the reading I just got and the math takes more time than the required A/D delay. I end by re-selecting the first channel so it is ready for the next cycle of readings.
_________________
The search for better is endless. Instead simply find very good and get the job done.
elasticman



Joined: 26 May 2009
Posts: 8

View user's profile Send private message

PostPosted: Fri May 29, 2009 3:13 am     Reply with quote

SherpaDoug wrote:
Yes, that is the sequence. I would have to look at your chip to see if 20us is the right time length. Usually I do math and storage on the reading I just got and the math takes more time than the required A/D delay. I end by re-selecting the first channel so it is ready for the next cycle of readings.


Well, from the link given to me up here, in this thread by PCM programmer
http://ww1.microchip.com/downloads/en/DeviceDoc/31023a.pdf

If I understand correctly it takes about 20 us for the A/D.
I'm using the PIC18F4431 processor.
Thanks for the help and the idea for the idea on how to end the function.
btw : Does what I wrote mean that it takes continuous readings?
I would appreciate it if you check and tell me if the 20us is enough:)
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Sun May 31, 2009 3:47 pm     Reply with quote

As long as your source resistance is under 10k and your temperature is reasonable, it looks to me like 20us acquisition time is enough.

this code
Code:
 
set_adc_channel(front_sensor);
delay_us(20);
data_from_front_sensor = READ_ADC();

set_adc_channel(right_sensor);
delay_us(20);
data_from_right_sensor = READ_ADC();

set_adc_channel(left_sensor);
delay_us(20);
data_from_left_sensor = READ_ADC();

will get a set of reading each time it is run. To get continuous readings you must run the code continuously.
_________________
The search for better is endless. Instead simply find very good and get the job done.
elasticman



Joined: 26 May 2009
Posts: 8

View user's profile Send private message

PostPosted: Mon Jun 08, 2009 3:27 am     Reply with quote

I'm having problems with my program and I'm in dire need for help.

This is my program :
Code:
#include <18F4431.H>

#device ADC=10

//#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#fuses HS, NOLVP
#use delay(clock = 20000000)

#define PWM_PIN0  PIN_B0 //for the driver board - enable always H for all motors
#define PWM_PIN1  PIN_B1 // motor1 - I1
#define PWM_PIN2  PIN_B2 // motor1 - I2
#define PWM_PIN3  PIN_B3 // motor2 - I3
#define PWM_PIN4  PIN_B4 // motor2 - I4
#define PWM_PIN5  PIN_D6 // motor3 - I1
#define PWM_PIN6  PIN_D7 // motor3 - I2

#define FRONT_SENSOR 6
#define RIGHT_SENSOR 7
#define LEFT_SENSOR 8

#define NUMBER_EQUATING_1_METER 0.65

int first_run_flag = 0;
long temp_data_from_front_sensor,temp_data_from_right_sensor,temp_data_from_left_sensor;
float distance_from_front_sensor,distance_from_right_sensor,distance_from_left_sensor;

//-------------------------------
void initialize_adc(void);
void activate_motors_1_and_2_to_move_forward(void);
void deactivate_motors_1_and_2(void);
void activate_all_motors_to_rotate_right(void);
void activate_all_motors_to_rotate_left(void);
void deactivate_all_motors(void);
void decide_what_to_do();
void read_sensors(void);
//====================================


void initialize_adc(void)
{
         setup_adc_ports( ALL_ANALOG );   //defines all pins to be analog
         setup_adc (ADC_CLOCK_INTERNAL);  // the adc uses the same clock speed as the board
}

void activate_motors_1_and_2_to_move_forward(void)
{
         output_high(PWM_PIN1);
         output_low(PWM_PIN2);
         output_low(PWM_PIN3);
         output_high(PWM_PIN4);
}

void deactivate_motors_1_and_2(void)
{
         output_low(PWM_PIN1);
         output_low(PWM_PIN2);
         output_low(PWM_PIN3);
         output_low(PWM_PIN4);
}

void activate_all_motors_to_rotate_right(void)
{
         output_high(PWM_PIN1);
         output_low(PWM_PIN2);
         output_high(PWM_PIN3);
         output_low(PWM_PIN4);
         output_high(PWM_PIN5);
         output_low(PWM_PIN6);
}

void activate_all_motors_to_rotate_left(void)
{
         output_low(PWM_PIN1);
         output_high(PWM_PIN2);
         output_low(PWM_PIN3);
         output_high(PWM_PIN4);
         output_low(PWM_PIN5);
         output_high(PWM_PIN6);
}

void deactivate_all_motors(void)
{
         output_low(PWM_PIN1);
         output_low(PWM_PIN2);
         output_low(PWM_PIN3);
         output_low(PWM_PIN4);
         output_low(PWM_PIN5);
         output_low(PWM_PIN6);
}

void decide_what_to_do()
{
         if ( distance_from_front_sensor>=NUMBER_EQUATING_1_METER ) // this is
         {                                                          // for the initial operation
               first_run_flag = 1;                                  // scan first
         }                                                          // to find the object
         while (first_run_flag == 0 )                               // then keep on
         {                                                          // following it
            activate_all_motors_to_rotate_right();                  //
            delay_ms(60);                                           //
            deactivate_all_motors();                                //
            delay_ms(60);                                           //
            read_sensors();                                         //
            if ( distance_from_front_sensor>=NUMBER_EQUATING_1_METER )//
            {                                                         //
               first_run_flag = 1;                                    //
            }                                                         //
         }                                                           
         if ( distance_from_front_sensor<NUMBER_EQUATING_1_METER ) //voltage is lower for farther object
         {
               while ( distance_from_front_sensor<NUMBER_EQUATING_1_METER )
               {
                  activate_motors_1_and_2_to_move_forward();
                  delay_ms(60);
                  deactivate_motors_1_and_2();
                  delay_ms(60);
                  read_sensors();
               }
         }
         if ( distance_from_right_sensor!= 0 )
         {
               while ( distance_from_right_sensor!= 0 )
               {
                  activate_all_motors_to_rotate_right();
                  delay_ms(60);
                  deactivate_all_motors();
                  delay_ms(60);
                  read_sensors();
               }
         }
         if ( distance_from_left_sensor!= 0 )
         {
               while ( distance_from_left_sensor!= 0 )
               {
                  activate_all_motors_to_rotate_left();
                  delay_ms(60);
                  deactivate_all_motors();
                  delay_ms(60);
                  read_sensors();
               }
         }
}

void read_sensors(void)
{
         set_adc_channel(front_sensor);
         delay_us(20);
         temp_data_from_front_sensor = READ_ADC( ADC_START_AND_READ );
         distance_from_front_sensor = temp_data_from_front_sensor*5/1023;
         set_adc_channel(right_sensor);
         delay_us(20);
         temp_data_from_right_sensor = READ_ADC( ADC_START_AND_READ );
         distance_from_right_sensor = temp_data_from_right_sensor*5/1023;
         set_adc_channel(left_sensor);
         delay_us(20);
         temp_data_from_left_sensor = READ_ADC( ADC_START_AND_READ );
         distance_from_left_sensor = temp_data_from_left_sensor*5/1023;
}

void main()
{
   initialize_adc();
   output_high(PWM_PIN0); //for the driver board - always have the "enabled" pin set to H ,for all motors
   do
   {
      read_sensors();
      decide_what_to_do();
   }  while (TRUE);
}


if anybody sees whats wrong...please do tell
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 08, 2009 11:39 am     Reply with quote

There is a recent discussion here, about how get the correct result
from a math expression when some of the terms are integers and
some are floating point:
http://www.ccsinfo.com/forum/viewtopic.php?t=39140

To trouble-shoot a problem, you need to use printf statements to
display intermediate values in your program. This will tell you
where the problem may be. If the values are not as expected,
then look closely at the code that does your calculations.
For example, you are assuming that this line has a full floating
point result as the output. But does it ?
Quote:
distance_from_front_sensor = temp_data_from_front_sensor*5/1023;

Suppose the numerator is 512. Then the result should be:
Quote:
(512 * 5)/1023 = 2.50

But, if we run the test program shown below, we get:
Quote:
result = 2.000

It's truncating the result to an integer. (Though it's still put
into the floating point variable).

You can read that link about math calculations. It tells you
what needs to be changed in the expression so it will give
the correct output of 2.50.
Code:
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

long temp_data_from_front_sensor,temp_data_from_right_sensor,temp_data_from_left_sensor;
float distance_from_front_sensor,distance_from_right_sensor,distance_from_left_sensor;


//======================================
void main()
{
temp_data_from_front_sensor = 512;

distance_from_front_sensor = temp_data_from_front_sensor*5/1023;

printf("result = %7.3f", distance_from_front_sensor);


while(1);
}

There may be other problems with your code, but this was one of them.
If you want more help, you need to provide a link to the motor driver
board schematic or webpage (and the part number). Also provide info
on the motors.
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Mon Jun 08, 2009 2:24 pm     Reply with quote

Regarding this line of code:

Code:

temp_data_from_front_sensor = READ_ADC( ADC_START_AND_READ );


Isn't the read_adc function void?
Shouldn't it just be:


Code:

temp_data_from_front_sensor = READ_ADC( );


In addition, if you have something like this:
Code:

distance_from_front_sensor = temp_data_from_front_sensor*5/1023;

You are probably going to get an integer back, either 0, 1, 2, 3, 4, or 5. You declared temp_data_from_front_sensor as an integer and you are mulitiplying it by 5, an integer, then dividing it back 1023, again an integer. I think what you want to do is something like:



Code:

distance_from_front_sensor = (long)temp_data_from_front_sensor*5.0/1023


Last edited by mkuang on Mon Jun 08, 2009 2:33 pm; edited 2 times in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 08, 2009 2:27 pm     Reply with quote

It's the same thing. From the manual:
Quote:
read_adc( )
Syntax: value = read_adc ([mode])

ADC_START_AND_READ (continually takes readings, this is the default)

But you're right, normally, we just use read_adc().
elasticman



Joined: 26 May 2009
Posts: 8

View user's profile Send private message

PostPosted: Tue Jun 09, 2009 12:26 am     Reply with quote

Thanks a lot guys.
We have managed to get it to work.
Somebody helped us and actually changed some of the stuff you are talking about before seeing what you wrote....
and the logic of the program seemed to work:)
Next week we will be connecting EVERYTHING and giving it a go:)
Thanks a LOT PCM Programmer and SherpaDoug , you guys are a great help!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group