|
|
View previous topic :: View next topic |
Author |
Message |
JeffLewcock
Joined: 10 Apr 2007 Posts: 29
|
SMBus / I2C Problem |
Posted: Wed Apr 06, 2011 7:30 am |
|
|
Hi All
I am having a problem (I think) with reading of a SMBus sensor
The sensor is a Melexis MLX90615 IR Thermometer
Data sheet here
http://www.melexis.com/Assets/IR-sensor-thermometer-MLX90615-Datasheet-5477.aspx
Page 12 has the timing diagram
I have written a little code to try and read the device but does not seem to work
I 'scoped the SDA and SCL lines and appear to have a bit being output by the PIC that I cannot change
The sensor seems to require the "R/W" bit (Bit 9) to be "0" but the PIC always sends a "1"
It seem to do this for all writes as the second byte "0x07" has it as well
Any help would be very welcome
Code
Code: | #include <Trial.h>
int8 DATA;
void main()
{
while(true){
output_low(LED);
delay_ms(DELAY);
printf ("Hello World");
Delay_ms(100);
i2c_start(); // Start condition
i2c_write(0x5b); // Slave Address
i2c_write(0x07); // Device address/
//i2c_write(0x5b); // Slave Address
//DATA = i2c_read();
//DATA1 = i2c_read();
//DATA2 = i2c_read();
printf ("%4x",DATA);
output_high(LED);
delay_ms(DELAY);
i2c_stop();
}}
|
Trial.h
Code: | #include <16F877.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 rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PORT1)
#use i2c(Master,FORCE_HW,Fast=50000,SMBUS,sda=PIN_C4,scl=PIN_C3)
#define LED PIN_B7
#define DELAY 100
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19492
|
|
Posted: Wed Apr 06, 2011 8:22 am |
|
|
Not bit 9.
Look again at the diagram. The format is start. Then an 8 bit data byte, with the last bit as '0' for a write. Then the acknowledge from the slave. The 9th bit is from the slave, not the PIC.
As with I2C, _you_ have to turn the bus around after you have selected the address, so you have to send a restart, then the device address again, with the eight bit reversed. The format should be:
So you need:
Code: |
i2c_start(); // Start condition
i2c_write(0x5A); // Slave Address - write bit low - the '1' here is the
//bit number in the diagram, _not_ the value....
i2c_write(0x07); // Register address
I2C_start() //Restart the bus
i2c_write(0x5b); // Slave Address - write bit high for a read
DATA = i2c_read();
DATA1 = i2c_read();
DATA2 = i2c_read(0); //You need to _NACK_ the last byte
i2c_stop();
//Then print your data etc..
|
If you look at the bit patterns given in the data sheet, rather than the text, you will see that 5A is sent on the first address transaction. You will also see the NACK on the last byte, and the note 'RS' for 'restart' before the second address is sent.
Best Wishes
Last edited by Ttelmah on Wed Apr 06, 2011 8:36 am; edited 1 time in total |
|
|
JeffLewcock
Joined: 10 Apr 2007 Posts: 29
|
|
Posted: Wed Apr 06, 2011 8:25 am |
|
|
Hi Ttelmah
Thanks very much for that, Its a long time since I have programmed a PIC
And you helped me last time, 5 years ago !!
Thanks Again
Jeff |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19492
|
|
Posted: Wed Apr 06, 2011 8:46 am |
|
|
Only recently then....
The most 'fun' thing I had about how long I have been using the PIC, was when Microchip published a page giving the history of the chip, and saying that the first flash chips had been released in a particular year. I had to point out to them that I had a product still in use, which had been released a year _earlier_ than their date, and used these chips. There was a stunned pause, then the realisation that a limited batch had been shipped to some customers the year before. They updated their history....
Best Wishes |
|
|
JeffLewcock
Joined: 10 Apr 2007 Posts: 29
|
|
Posted: Thu Apr 07, 2011 6:39 am |
|
|
Hi Ttelmah
Something still wrong with the code (or the device(more likely))
The device will not "ACK" for some reason. I have some screenshots from my scope but cant seem to upload them to the forum Grrrr
Re The time the forums seem to to have you as a member for only one year and me for 3
When we both know we communicated in 2005 !!!
Jeff |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19492
|
|
Posted: Thu Apr 07, 2011 7:59 am |
|
|
If you search back, you will find posts from me, going back to the very earliest days of CCS. Thing was you didn't have to 'register' then. Only in the last few years has this been 'required'. Means I can't post from some locations, but helps reduce the garbage posts....
Not acking, implies it isn't recognising the address. The reason is that they are using 'Texas' addresses. The '5B' value they give, _is_ the device address, but is the upper 7 bits of the byte to send. So you need to use 0xB6, and 0xB7 for write and read respectively.
So:
Code: |
i2c_start(); // Start condition
i2c_write(0xB6); // Slave Address - write bit low - the '1' here is the
//bit number in the diagram, _not_ the value....
i2c_write(0x07); // Register address
I2C_start() //Restart the bus
i2c_write(0xB7); // Slave Address - write bit high for a read
DATA = i2c_read();
DATA1 = i2c_read();
DATA2 = i2c_read(0); //You need to _NACK_ the last byte
i2c_stop();
//Then print your data etc..
|
Explains the reference to 0x5B being the address.
You can see this in the timing diagram.
I'd also suggest you pause for 20mSec, before you try to talk to the chip. Tpor in the data sheet.
Best Wishes |
|
|
JeffLewcock
Joined: 10 Apr 2007 Posts: 29
|
|
Posted: Mon Apr 18, 2011 2:31 am |
|
|
Hi Ttelmah
Got it working now, I was confused with the addressing of the devices on the I2C.
I was messing about with the CCS numeric convertor and then it hit me like a bolt of lightning !
Have the I2C reading 3 MLX90615's and a SHT2x now all fine
Thanks very much for the help
PS If anyone is using the MLX's they are VERY sensitive to supply decoupling, poor decoupling leads to low (or very low depending on how bad the decoupling is) object temperature readings !!
Jeff |
|
|
farouk_baya
Joined: 18 Jun 2010 Posts: 27
|
|
Posted: Fri Dec 19, 2014 11:59 am |
|
|
Hello;
I'm working in a project with mlx90615 and pic18f25k20.
I used the last posted code but the problem is that the returned value is always 0.
Here is my code:
-- The configuration of the PIC:
Code: |
#include "18f25k20.h"
#fuses MCLR,INTRC_IO,NOWDT,NOLVP,NOBROWNOUT,BORV18,NOPROTECT,DEBUG,NOSTVREN
#use delay(internal = 8M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=BTDATA)
#use i2c(master,FORCE_SW,Fast=50000,SMBUS, sda=PIN_C4, scl=PIN_C3)
#use fast_io (C)
|
-- the code for the mlx90615
Code: |
// get the temperature of the object
float get_temperature(int OBJECT_AMBIENT_TEMPERATURE, int fahrenheit_celsius) {
double tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90615)
double tempData = 0x0000; // zero out the data
int MSByte = 0x00, LSByte = 0x00, PEC = 0x00;
delay_ms(300);
i2c_start(); // Start condition
i2c_write(0xB6); // Slave Address - write bit low - the '1' here is the
//bit number in the diagram, _not_ the value....
i2c_write(0x07); // Register address
I2C_start(); //Restart the bus
i2c_write(0xB7); // Slave Address - write bit high for a read
LSByte = i2c_read();
printf("LSByte = %x \r\n",LSByte);
MSByte = i2c_read();
printf("MSByte = %x \r\n",MSByte);
PEC = i2c_read(0); //You need to _NACK_ the last byte
printf("PEC = %x \r\n",PEC);
i2c_stop();
// This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
tempData = (double)(((MSByte & 0x007F) << 8) + LSByte);
printf("tempData1 = %x \r\n",tempData);
tempData = (tempData * tempFactor) - 0.01;
printf("tempData2 = %x \r\n",tempData);
// temperature in Celsius
temperature_celsius = tempData - 273.15;
printf("temperature_celsius = %3.2f \r\n",temperature_celsius);
// temperature in Fahrenheit
temperature_fahrenheit = (temperature_celsius*1.8) + 32;
printf("temperature_fahrenheit = %3.2f \r\n",temperature_fahrenheit);
// fahrenheit_celsius = 0 ==> display the Celsius
// fahrenheit_celsius = 1 ==> display the Fahrenheit
if (fahrenheit_celsius == 0 ) {
// return the Celsius value
return temperature_celsius;
} else {
// return the Fahrenheit value
return temperature_fahrenheit;
}
}
|
And here the schematic:
http://www.4shared.com/download/IaNxjc0tce/sensor.jpg?lgfp=3000
The declaration of each variable is set in the main and it's already correct.
So is there any problem for the I2C instruction, addresses or schematic?
Thank you. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9220 Location: Greensville,Ontario
|
|
Posted: Fri Dec 19, 2014 12:38 pm |
|
|
I'd say the pullup resistors are too high,perhaps try 3K3 and retest.
Also download PCMP's 'I2C scanner' program from the code library and run it first to confirm your hardware is good.
jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Dec 19, 2014 2:33 pm |
|
|
You said the function return value is 0, but what do you get for your
raw data values, from the lines in bold below ?
Quote: | i2c_write(0xB7); // Slave Address - write bit high for a read
LSByte = i2c_read();
printf("LSByte = %x \r\n",LSByte);
MSByte = i2c_read();
printf("MSByte = %x \r\n",MSByte);
PEC = i2c_read(0); //You need to _NACK_ the last byte
printf("PEC = %x \r\n",PEC);
i2c_stop();
|
Here is the link for the i2c bus scanner program:
http://www.ccsinfo.com/forum/viewtopic.php?t=49713 |
|
|
farouk_baya
Joined: 18 Jun 2010 Posts: 27
|
|
Posted: Mon Dec 22, 2014 9:27 am |
|
|
Thanks for your answers.
I used the”i2c bus scanner program”. But there is a problem here. When I put the SDA pin to ‘1’ I get with the voltage measurement 0.886 V which is not enough to get ‘1’ in the SDA pin for the slave. Is it normal to get 0.886V instead of 3.3 V ?
Thanks. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19492
|
|
Posted: Mon Dec 22, 2014 9:47 am |
|
|
What do you mean 'put the pin to 1'?. On I2C, you only drive the pins low, or _release_ them (let them float). The pull-up is done by the bus resistors. Almost sounds as if you don't have the pull up resistors....
You should never physically drive the pin high (since then if another device is holding the bus, this will give an overload). |
|
|
farouk_baya
Joined: 18 Jun 2010 Posts: 27
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9220 Location: Greensville,Ontario
|
|
Posted: Mon Dec 22, 2014 10:58 am |
|
|
300K ??? !!!!
HOW did you calculate 300Kohms ??
NO....maybe 3K3.... 3300 ohms, at least I'd start there if running 3 volts.....
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19492
|
|
Posted: Mon Dec 22, 2014 11:46 am |
|
|
For a 3.3v system, with 10pF bus capacitance, SMBUS specifies the _maximum_ pull up as 10K, and the minimum at 1K2R.....
If your bus capacitance is higher than this, the maximum resistor falls. |
|
|
|
|
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
|