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 CCS Technical Support

SMBus / I2C Problem
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
JeffLewcock



Joined: 10 Apr 2007
Posts: 29

View user's profile Send private message

SMBus / I2C Problem
PostPosted: Wed Apr 06, 2011 7:30 am     Reply with quote

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: 19480

View user's profile Send private message

PostPosted: Wed Apr 06, 2011 8:22 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Apr 06, 2011 8:25 am     Reply with quote

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: 19480

View user's profile Send private message

PostPosted: Wed Apr 06, 2011 8:46 am     Reply with quote

Only recently then.... Smile

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

View user's profile Send private message

PostPosted: Thu Apr 07, 2011 6:39 am     Reply with quote

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: 19480

View user's profile Send private message

PostPosted: Thu Apr 07, 2011 7:59 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Apr 18, 2011 2:31 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Dec 19, 2014 11:59 am     Reply with quote

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: 9216
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Dec 19, 2014 12:38 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Dec 19, 2014 2:33 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 22, 2014 9:27 am     Reply with quote

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: 19480

View user's profile Send private message

PostPosted: Mon Dec 22, 2014 9:47 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 22, 2014 10:10 am     Reply with quote

Screenshot from the datasheet:

http://www.4shared.com/download/cuC53yx_ce/MLX9015.jpg?lgfp=3000


The following the previous image from the datasheet, I think the correct values for the two pull-ups are 300k. Is it correct?
temtronic



Joined: 01 Jul 2010
Posts: 9216
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Dec 22, 2014 10:58 am     Reply with quote

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: 19480

View user's profile Send private message

PostPosted: Mon Dec 22, 2014 11:46 am     Reply with quote

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.
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, 3  Next
Page 1 of 3

 
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