|
|
View previous topic :: View next topic |
Author |
Message |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Mar 13, 2012 12:39 pm |
|
|
Here is a diagnostic program (see below) which will look for any i2c slave
devices that are on the i2c bus, and report the slave address for each
one. For example, if I run this program on my PicDem2-Plus board, it
shows the following result in a terminal window (TeraTerm) on my PC:
Quote: |
Start:
ACK addr: 9A
ACK addr: A0
Number of i2c chips found: 2
|
This means it found the TC74 temperature chip (slave address 0x9A)
and the 24LC256 eeprom (slave address 0xA0). Run the program on
your board and see what it finds.
Code: |
#include <16F887.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=4M)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
// 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);
}
//=================================
void main()
{
int8 i;
int8 status;
int8 count = 0;
printf("\n\rStart:\n\r");
delay_ms(1000);
// Try all slave addresses from 0x10 to 0xEF.
// See if we get a response from any slaves
// that may be on the i2c bus.
for(i=0x10; i < 0xF0; i+=2)
{
status = get_ack_status(i);
if(status == TRUE)
{
printf("ACK addr: %X\n\r", i);
count++;
delay_ms(2000);
}
}
if(count == 0)
printf("\n\rNothing Found");
else
printf("\n\rNumber of i2c chips found: %u", count);
while(1);
}
|
-----
Edit: Added carriage return/ linefeed to properly format the output.
Last edited by PCM programmer on Wed Mar 14, 2012 12:05 pm; edited 1 time in total |
|
|
Jampe
Joined: 09 Mar 2012 Posts: 27
|
|
Posted: Wed Mar 14, 2012 11:30 am |
|
|
PCM programmer , thank you for your demo but I got this :
Quote: |
Start:
ACK addr: 10ACK addr: 12ACK addr: 14ACK addr:
16ACK addr: 18ACK addr: 1AACK addr: 1CACK addr
: 1EACK addr: 20ACK addr: 22ACK addr: 24ACK ad
dr: 26ACK addr: 28ACK addr: 2AACK addr: 2CACK
addr: 2EACK addr: 30ACK addr: 32ACK addr: 34AC
K addr: 36ACK addr: 38ACK addr: 3AACK addr: 3C
ACK addr: 3EACK addr: 40ACK addr: 42ACK addr:
44ACK addr: 46ACK addr: 48ACK addr: 4AACK addr
: 4CACK addr: 4EACK addr: 50ACK addr: 52ACK ad
dr: 54ACK addr: 56ACK addr: 58ACK addr: 5AACK
addr: 5CACK addr: 5EACK addr: 60ACK addr: 62AC
K addr: 64ACK addr: 66ACK addr: 68ACK addr: 6A
ACK addr: 6CACK addr: 6EACK addr: 70ACK addr:
72ACK addr: 74ACK addr: 76ACK addr: 78ACK addr
: 7AACK addr: 7CACK addr: 7EACK addr: 80ACK ad
dr: 82ACK addr: 84ACK addr: 86ACK addr: 88ACK
addr: 8AACK addr: 8CACK addr: 8EACK addr: 90AC
K addr: 92ACK addr: 94ACK addr: 96ACK addr: 98
ACK addr: 9AACK addr: 9CACK addr: 9EACK addr:
A0ACK addr: A2ACK addr: A4ACK addr: A6ACK addr
: A8ACK addr: AAACK addr: ACACK addr: AEACK ad
dr: B0ACK addr: B2ACK addr: B4ACK addr: B6ACK
addr: B8ACK addr: BAACK addr: BCACK addr: BEAC
K addr: C0ACK addr: C2ACK addr: C4ACK addr: C6
ACK addr: C8ACK addr: CAACK addr: CCACK addr:
CEACK addr: D0ACK addr: D2ACK addr: D4ACK addr
: D6ACK addr: D8ACK addr: DAACK addr: DCACK ad
dr: DEACK addr: E0ACK addr: E2ACK addr: E4ACK
addr: E6ACK addr: E8ACK addr: EAACK addr: ECAC
K addr: EE
Number of i2c chips found: 112
|
By the way , I bought the pull-up resistors (1.8k) as you said , it doesn't solve my problem and jeremiah's code is showing me "0f" .
Where am I wrong?
I've done everything you told me.
Again , I'm very glad you are trying to help me..
Jampe. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Mar 14, 2012 12:38 pm |
|
|
I'm sorry about the bad formatting. I posted a slightly earlier version of
the code and it was missing some carriage returns. I have edited my
post and the correct code is now there.
With regard to the output you posted, it obvious it's getting an ACK on
every address. I was able to simulate this by grounding pin C4.
So I wonder if your connections are correct.
Do you have pull-up resistors on pins C3 and C4 ? Or did you accidently
install pull-down resistors by mistake ? Or is some other connection
incorrect, such as power and ground ?
Your pull-up resistor connections should be like this:
Code: |
+5v
|
<
> 1.8K
<
To PIC | To i2c slave
pin C4 ------------------ SDA pin
+5v
|
<
> 1.8K
<
To PIC | To i2c slave
pin C3 ------------------ SCL pin
|
|
|
|
Jampe
Joined: 09 Mar 2012 Posts: 27
|
|
Posted: Wed Mar 14, 2012 2:48 pm |
|
|
Thank you for your reply , I used your new code and this is the output :
Quote: |
Start:
ACK addr: E4
Number of i2c chips found: 1
|
I checked the connections and they seems alright.
If the addr is E4 , so my write address is E4?
Thanks,
Jampe. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Mar 14, 2012 2:54 pm |
|
|
Yes, the write address is 0xE4, and the read address is 0xE5.
So your #define statements should look like this:
Code: |
#define I2C_WRITE_ADDR 0xE4
#define I2C_READ_ADDR 0xE5
|
|
|
|
Jampe
Joined: 09 Mar 2012 Posts: 27
|
|
Posted: Wed Mar 14, 2012 3:03 pm |
|
|
I wrote as you say and it shows "data=08" all the time.
This is the code :
Code: |
#include <16F887.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay (clock=20000000)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define I2C_WRITE_ADDR 0xE4
#define I2C_READ_ADDR 0xE5
void main()
{
int8 data;
while(TRUE)
{
i2c_start(); // initiate start condition
i2c_write(I2C_WRITE_ADDR); // device address
i2c_write(0x00); // register address
i2c_start();
i2c_write(I2C_READ_ADDR); // device address
data = i2c_read(0);
i2c_stop();
printf("data=%x\n",data);
}
}
|
Maybe is the component broken ? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1345
|
|
Posted: Wed Mar 14, 2012 3:06 pm |
|
|
I believe that code just reads the Firmware version or board version, so the value won't change. If it is indeed a revision 8, then that part looks good.
If you want to read the light sensor value, then change the 0x00 to 0x01. If you want to read the first echo high byte, then change 0x00 to 0x02, etc. This is all in the tables located on the page you linked to me in an earlier post.
If you want to read multiple bytes, then change the code to:
Code: |
#include <16F887.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay (clock=20000000)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define I2C_WRITE_ADDR 0xE4
#define I2C_READ_ADDR 0xE5
void main() {
int8 data[2]; //keep track of the size of this!
while(TRUE){
i2c_start(); // initiate start condition
i2c_write(I2C_WRITE_ADDR); // device address
i2c_write(0x02); // register address
i2c_start();
i2c_write(I2C_READ_ADDR); // device address
data[0] = i2c_read();
data[1] = i2c_read(0); //NACK last byte
i2c_stop();
printf("data=%x %x\n",data[0],data[1]);
}
}
|
EDIT: This is assuming of course that the device lets you read more than one byte at a time. If it doesn't, then issue the previous code twice using different register addresses |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Mar 14, 2012 3:32 pm |
|
|
Try this code to get the range in inches. I don't guarantee this works
because I don't have an SRF08 to test.
Code: |
#include <16F887.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4M)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define SRF08_WRT_ADDR 0xE4
#define SRF08_RD_ADDR 0xE5
int16 srf08_get_range(void);
//=======================
void main()
{
int16 result;
while(1)
{
result = srf08_get_range();
printf("Range in inches = %lu\n\r", result);
delay_ms(1000);
}
}
//========================
int16 srf08_get_range(void)
{
int8 lsb;
int8 msb;
int16 range;
// This 1st part sends the ranging command
// to the SRF08 to start it ranging.
i2c_start();
i2c_write(SRF08_WRT_ADDR);
i2c_write(0);
i2c_write(80); // The range will be returned in inches
i2c_stop();
// Now wait for the ranging to complete.
delay_ms(100); // Must be 65 ms minimum.
// Finally get the range from the SRF08.
i2c_start();
i2c_write(SRF08_WRT_ADDR);
i2c_write(2);
i2c_start();
i2c_write(SRF08_RD_ADDR);
msb = i2c_read();
lsb = i2c_read(0);
i2c_stop();
range = make16(msb, lsb);
return(range);
} |
|
|
|
Jampe
Joined: 09 Mar 2012 Posts: 27
|
|
Posted: Thu Mar 15, 2012 12:47 am |
|
|
Thank you for your codes..
jeremiah , your code output "data=00 00"..
PCM programmer , your code didn't print anything.
Does that make sense?
For be sure , this is the way I've connected the sensor :
http://img818.imageshack.us/img818/179/img3669copy.jpg
Thanks ,
Jampe. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9224 Location: Greensville,Ontario
|
|
Posted: Thu Mar 15, 2012 5:39 am |
|
|
Electronics101...
From your picture, it appears you've connected the resistors in 'series' NOT in 'parallel'.
Consult any I2C device's datasheet to see how the I2C bus 'pullup' resistors are connected. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 15, 2012 9:35 am |
|
|
Go to this page and scroll down to the photo for "Arduino and two-wire
interface":
http://nearfuturelaboratory.com/tag/diy/
There you will see two photos with an X,Y,Z board. These photos show
how to install pull-up resistors.
Notice in each photo, two wires are connected between the X,Y,Z board
and another board. These are the SCL and SDA connection wires.
Also each photo shows two resistors going from SCL and SDA to the
Vcc power bus. Power is marked with a red stripe on the breadboard.
In your case, Vcc = +5 volts.
That's how you're supposed to do it. I showed you this in the schematic
that I posted earlier. |
|
|
Jampe
Joined: 09 Mar 2012 Posts: 27
|
|
Posted: Thu Mar 15, 2012 10:08 am |
|
|
Thank you all! it works!
temtronic, thanks for your explanation.
PCM programmer, your code is working! Thank you all for your help.
Thank you for your patience and rapidly responses!
The SRF08 sensor works!
I tried to change this code to my ADXL345 sensor I don't see anything..
It connected as "9 Degrees of Freedom - Sensor Stick" so I didn't use pull-up resistors (built-in).
http://www.sparkfun.com/products/10724
Code: |
#include <i2c4.h>
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define WRT_ADDR 0xA6
#define RD_ADDR 0xA7
int16 adxl345_get_data(void);
//=======================
void main()
{
int16 result;
while(1)
{
result = adxl345_get_data();
printf("data = %lu\n\r", result);
delay_ms(1000);
}
}
//========================
int16 adxl345_get_data(void)
{
int8 lsb;
int8 msb;
int16 data;
i2c_start();
i2c_write(WRT_ADDR);
i2c_write(0);
i2c_write(0x32); // X-axis
i2c_stop();
delay_ms(100); // Waiting 100ms
// Finally get the data from the ADXL345
i2c_start();
i2c_write(WRT_ADDR);
i2c_write(2);
i2c_start();
i2c_write(RD_ADDR);
msb = i2c_read();
lsb = i2c_read(0);
i2c_stop();
data = make16(msb, lsb);
return(data);
}
|
Thanks ,
Jampe. |
|
|
jcal54321
Joined: 06 Mar 2009 Posts: 10 Location: Salinas, CA
|
I2C tester code from PCM Programmer works great! |
Posted: Sat Jun 09, 2012 6:39 pm |
|
|
I just wanted to add that the I2C tester program posted here works great. I am using a PIC18F2520 and communicating with all three sensors on Sparkfun's 9DOF Stick (P/N SEN-10724).
Since my PIC is working with 5 VDC and the 9DOF Stick is working from 3.3 VDC, I had to use a TI P82B96 Dual Bidirectional Bus Buffer in between the two components. I connected the IC per Figure 2 of the P82B96 datasheet. Pins 1 and 7 connected directly to SDA and SCL of the 9DOF Stick. Pins 2 and 3, which are tied together as shown in Figure 2, are pulled up to 5 VDC through a 2.6K resistor and connected to SDA on the PIC. A similar configuration for pins 5 and 6 to SCL on the PIC.
Anyway, just wanted to post this, in case anyone will find it useful. The I2C tester code is a great place to start. Here is the output from the program received by Hyperterminal:
Code: | Start:
ACK addr: 3C
ACK addr: A6
ACK addr: D0
Number of i2c chips found: 3 |
|
|
|
|
|
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
|