|
|
View previous topic :: View next topic |
Author |
Message |
znses
Joined: 15 Apr 2011 Posts: 9
|
I need a HELP ! |
Posted: Fri Apr 15, 2011 12:28 am |
|
|
I am using ICD3 & PIC16F877A and two srf08 sonar sensors and I do face a problem in distinguishing and detection of both sensors. On an individual basis for 1 sensor the code work successfully but once I interface the second sensor the output fail.
Summary: This program stores the 1st echo of srf08 and if the object is less than 50 cm LED B0 and B1 glitter, so could anyone help me to figure out the error ?
Code: |
#include <16f877a.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
main()
{
int i; int16 range[1]=0; int16 range[1]=0;
set_tris_b(0);
while(1)
{
i2c_start(); // initiate start condition
i2c_write(0xE0); // device address
i2c_write(0x00); // register address
i2c_write(0x54); // set units to cm
i2c_stop();
delay_ms(105); // wait for returning ping
i2c_start(); // initiate a new start condition
i2c_write(0xE0); // device address
i2c_write(0x02); // address of high byte register
i2c_start();
i2c_write(0xE1); // device address put to read
for (i=0;i<17;i++)
{
range[i] = i2c_read(1); // read first byte and shift to the left
range[i] = range[i] << 8;
if(i<16)
range[i] += i2c_read(1); // read second byte and add to 1st
else
range[i] += i2c_read(0);
}
i2c_stop();
for (i=0;i<1;i++)
{
printf("range in cm = %lu\n\r", range[i]);
}
output_B(0x00); // setting LED B0 B1 B2 to low
if (range[i]<50) // Set threshold to 50 cm
{
output_high(Pin_B0); // give high output when statement is true
}
i2c_start(); // initiate start condition
i2c_write(0xA0); // device new address
i2c_write(0xAA); // device new address
i2c_write(0xA5); // device new address
i2c_write(0xE4); // device address
i2c_write(0x00); // register address
i2c_write(0x54); // set units to cm
i2c_stop();
delay_ms(105); // wait for returning ping
i2c_start(); // initiate a new start condition
i2c_write(0xE4); // device address
i2c_write(0x02); // address of high byte register
i2c_start();
i2c_write(0xE5); // device address put to read
for (i=0;i<17;i++)
{
rangey[i] = i2c_read(1); // read first byte and shift to the left
rangey[i] = rangey[i] << 8;
if(i<16)
rangey[i] += i2c_read(1); // read second byte and add to 1st
else
rangey[i] += i2c_read(0);
}
i2c_stop();
for (i=0;i<1;i++)
{
printf("range in cm = %lu\n\r", rangey[i]);
}
output_B(0x00);
if (rangey[i]<50) // Set threshold to 50 cm
{
output_high(Pin_B1); // give high output when statement is true
}}} |
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Apr 15, 2011 5:46 am |
|
|
Code: | int i; int16 range[1]=0; int16 range[1]=0; | You are initialising the same array twice? Sloppy programming.
A real bug is that you are writing outside the array bounds. Range[1] declares only 1 int16, but you are using the array as if it has a size of 17 elements. |
|
|
znses
Joined: 15 Apr 2011 Posts: 9
|
|
Posted: Fri Apr 15, 2011 12:50 pm |
|
|
sorry typo-error the second variable is int16 rangey[1]=0; It is not the same ... so Is there any error associated with the structure, initialization , usage of I2C or ranging ?>
Thanks alot for your contribution |
|
|
znses
Joined: 15 Apr 2011 Posts: 9
|
|
Posted: Fri Apr 15, 2011 12:54 pm |
|
|
Do you mean that int16 range[1]=0; should be int16 range[17]=0; instead ?
But we will send only 1 rather than the 17th echos that is why I initialized the array to hold 1 element only because I want to store the 1st echo only ....
Thanks again....... |
|
|
cerr
Joined: 10 Feb 2011 Posts: 241 Location: Vancouver, BC
|
|
Posted: Fri Apr 15, 2011 12:55 pm |
|
|
znses wrote: | sorry typo-error the second variable is int16 rangey[1]=0; |
But that array still contains one element only, you want something like int16 rangey[X] (X being the number of elements you require) |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Fri Apr 15, 2011 1:09 pm |
|
|
If you're only storing the first echo, you do not need an array. A simple variable is all that is needed. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 15, 2011 1:25 pm |
|
|
I'm not sure what you're trying to do. First you talk to the SRF08,
then you try to change the i2c address.
Do you two SRF08 devices on the same i2c bus ? When they come
from the manufacturer, they are all set to address 0xE0. Read this
section of their tech info:
Quote: | Changing the I2C Bus Address |
http://www.robot-electronics.co.uk/htm/srf08tech.shtml
They say that to change the i2c address, that you must have only one
SRF08 device on the bus. Are you doing that ?
The idea is, you buy two SRF08 devices. Then you put one of them on
your PIC's i2c bus. You run a special progam (following their instructions)
and change the i2c address of that one SRF08. When you're done,
you now have one device at 0xE0, and the 2nd one is at 0xE4 (let's say).
Now you can put both devices on the same i2c bus and you can
talk to both of them. Then it will work. |
|
|
znses
Joined: 15 Apr 2011 Posts: 9
|
|
Posted: Fri Apr 15, 2011 1:42 pm |
|
|
I was setting the two sensors at the same I2C and at the same time do you mean I have to connect 1 sensor using the same program then I connect the second sensor to I2C Pic's lines ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 15, 2011 1:49 pm |
|
|
I mean:
1. Connect only one sensor to the PIC.
2. Make a special "i2c address changing" program, which you will run
only one time.
3. Run the address changing program on the sensor. It now has a new
i2c address. (Let's say it's now 0xE4).
4. Don't change the address of the other sensor. Leave it at the factory
address of 0xE0.
Now,
A. Connect both sensors to the PIC, on the same i2c bus.
B. Write a program that will read the data from each sensor.
Use the correct i2c address (0xE0 or 0xE4) to talk to the desired sensor.
And especially,
Don't run the "address changing" program again. You only need it once.
Your purpose is to change the address of ONE of the sensors, so it's
different than the factory default address.
-------------
If you can't understand this, another way to do the project is to have two
i2c busses. In other words, use 2 pins for the first bus, and use two other
PIC pins for the 2nd bus. (Total of 4 PIC pins are required).
Then you can use "streams" with the #use i2c() statement, and in
the CCS i2c functions, you can specify a "stream" to tell the compiler
which i2c bus to use.
Maybe that's too difficult also. Maybe do it the first way. |
|
|
znses
Joined: 15 Apr 2011 Posts: 9
|
|
Posted: Fri Apr 15, 2011 2:06 pm |
|
|
Regarding address changing program >> The first method
The following program can be called as I2C address changing program ?
Code: |
#include <16f877a.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
main()
{
i2c_start(); // initiate start condition
i2c_write(0xA0); // device new address
i2c_write(0xAA); // device new address
i2c_write(0xA5); // device new address
i2c_write(0xE4); // device address
i2c_stop();
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 15, 2011 4:19 pm |
|
|
The program to change the SRF08 i2c address should look more like this.
I don't have an SRF08 to test, but I think this program has a chance to work.
Code: |
#include <16F877.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#define SRF08_NEW_ADDR 0xE4 // Set your new address here
#define SRF08_CURRENT_ADDR 0xE0 // Factory Default
#define SRF08_CMD_REG 0x00 // Address of Command Register
//-------------------------------------
void srf08_write_byte(int8 dev_addr, int8 reg, int8 data)
{
i2c_start();
i2c_write(dev_addr);
i2c_write(reg);
i2c_write(data);
i2c_stop();
}
//---------------------------------
// Send the special sequence that allows you to change
// the i2c address.
void srf08_set_new_address(int8 new_addr)
{
srf08_write_byte(SRF08_CURRENT_ADDR, SRF08_CMD_REG, 0xA0);
srf08_write_byte(SRF08_CURRENT_ADDR, SRF08_CMD_REG, 0xAA);
srf08_write_byte(SRF08_CURRENT_ADDR, SRF08_CMD_REG, 0xA5);
srf08_write_byte(SRF08_CURRENT_ADDR, SRF08_CMD_REG, new_addr);
}
//------------------------------------
// This function writes the slave address to the i2c bus.
// If a slave chip is at that address, it should respond to
// this with an "ACK". This function returns TRUE if an
// ACK was found. Otherwise it returns FALSE.
int8 get_ack_status(int8 address)
{
int8 status;
i2c_start();
status = i2c_write(address); // Status = 0 if got an ACK
i2c_stop();
if(status == 0)
return(TRUE);
else
return(FALSE);
}
//--------------------------------------
// Scan i2c addreses 0x10 to 0xF6.
// Return the address of 1st device found, if any.
// If nothing found, return 0.
int8 find_first_i2c_device(void)
{
int8 i;
for(i=0x10; i<0xF8; i+=2)
{
if(get_ack_status(i)) // Did we find an i2c device ?
return(i); // If so, return the address
}
return(0); // If nothing found after scan, return 0
}
//==========================================
void main()
{
int8 addr;
addr = find_first_i2c_device();
if(addr)
printf("Initial address = %X \n\r", addr);
else
printf("Initial address not in range 0x10 to 0xF6\n\r");
printf("Setting new address to %X \n\r", SRF08_NEW_ADDR);
srf08_set_new_address(SRF08_NEW_ADDR);
addr = find_first_i2c_device();
if(addr)
printf("Found new address = %X \n\r", addr);
else
printf("New address not in range 0x10 to 0xF6\n\r");
printf("Done\n\r");
while(1);
} |
|
|
|
|
|
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
|