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

LM75 Addressing Problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jleblanc



Joined: 17 May 2006
Posts: 9

View user's profile Send private message

LM75 Addressing Problem
PostPosted: Tue Aug 01, 2006 12:48 pm     Reply with quote

Hello,

I'm trying to develop some code that will allow me to talk to multiple LM75 temperature sensors on an I2C bus. The problem I'm having though is my code will only communicate with an LM75 at it's base address (A0-A2 pins on the LM75 all grounded). When I try to communicate with a chip on base address+1 (A0 high, A1-A2 ground) my code doesn't work. I've posted my code below, any ideas?

When I'm conducting my tests I only have the one LM75 on the I2C bus.

Thanks!

Code:
double LM75_ReadTemperatureRegister(unsigned int pAddress)
{
   unsigned long Data=0;
   unsigned int Address=0;
   unsigned int HiByte=0;
   unsigned int LoByte=0;
   double Temperature=0;

   Address=LM75_BASE_ADDRESS | pAddress;
   Address<<=1;

   i2c_start();
   i2c_write(Address);
   i2c_write(LM75_TEMP_REG);
   i2c_start();
   i2c_write(Address | 1);
   HiByte=i2c_read();
   LoByte=i2c_read();
   i2c_stop();

   Data=make16(HiByte,LoByte);
   Data>>=5; //lower 5 bits aren't used

   //test the sign bit
   if (Data & 1024!=1) //temperature is positive
   {
      Temperature=Data*0.125;
   }
   else //temperature is negative
   {
      Temperature=(0-Data)*0.125;
   }
   
   return(Temperature);
}


Here's how I2C is setup in my program:

Code:
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3)


So calling

Code:
LM75_ReadTemperatureRegister(0);


Will work with an LM75 on that address but calling

Code:
LM75_ReadTemperatureRegister(1);


Does not.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 1:03 pm     Reply with quote

Please edit your post, and fix the garbled lines of code, and
then submit the post with the checkbox for "Disable HTML in this post"
selected. If you use Less Than or Greater Than symbols with HTML
enabled, your code will get scrambled. The checkbox is directly
below the posting composition window.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 1:42 pm     Reply with quote

OK, that's better.

I see one immediate problem. The last i2c_read() needs to do a "NAK".
In CCS, this is done by giving the function a 0 parameter. Change
your code so it does this. See the line shown in bold below.
Quote:
i2c_start();
i2c_write(Address);
i2c_write(LM75_TEMP_REG);
i2c_start();
i2c_write(Address | 1);
HiByte=i2c_read();
LoByte=i2c_read(0);
i2c_stop();


I didn't really look closely at the rest of your code. If that doesn't
fix the problem, then post the #define statements for your constants,
such as LM75_BASE_ADDRESS. Currently we don't know what those
are.
jleblanc



Joined: 17 May 2006
Posts: 9

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 1:59 pm     Reply with quote

That change didn't fix my problem.

Here are my constants:

Code:
#define LM75_BASE_ADDRESS        72
#define LM75_TEMP_REG            0
#define LM75_CONFIG_REG          1
#define LM75_HYSTERESIS_REG      2
#define LM75_OVERTEMP_REG        3
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 2:24 pm     Reply with quote

I think you need to show a small test program that shows how
you are calling the LM75 function with different addresses.

There's another bug in your program. This line right here
is not doing what you think it's doing.
Quote:
if (Data & 1024!=1) //temperature is positive

The '!=' operator has high precedence than the '&' operator.
But even if you fix that, there's a still a problem. You're assuming
that the expression of (Data & 1024) is automatically converted
to a boolean (0 or 1), and it's not. You need to spend some
more time on your if() statement, and run some test programs
so you understand it.

One more thing. You're using decimal numbers throughout your code.
Decimal is not the best radix to use for register operations. The
registers are usually best thought of in terms of bitmasks or bitfields,
and for me, hex is the best. Other people might use binary notation.
Using decimal just doesn't give the best 'feel' for this type of coding.
jleblanc



Joined: 17 May 2006
Posts: 9

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 2:30 pm     Reply with quote

Quote:
You're assuming
that the expression of (Data & 1024) is automatically converted
to a boolean (0 or 1), and it's not


I thought in C 0 is false and anything >0 is true?

Edit: Oops - I see the mistake in my if statement now.

I'll post a test program shortly.
jleblanc



Joined: 17 May 2006
Posts: 9

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 2:45 pm     Reply with quote

Here's a sample program:

Code:
#include <16F877A.h>
#device ICD=TRUE
#device adc=8

#fuses HS,WDT,NOPROTECT,NOLVP,PUT                 //No Watch Dog Timer
#FUSES
#use delay(clock=20000000)
#use i2c(Master,Fast,sda=PIN_B0,scl=PIN_B1)
#use rs232(DEBUGGER)

#define LM75_BASE_ADDRESS        72
#define LM75_TEMP_REG            0
#define LM75_CONFIG_REG          1
#define LM75_HYSTERESIS_REG      2
#define LM75_OVERTEMP_REG        3

double LM75_ReadTemperatureRegister(unsigned int pAddress)
{
   unsigned long Data=0;
   unsigned int Address=0;
   unsigned int HiByte=0;
   unsigned int LoByte=0;
   double Temperature=0;

   Address=LM75_BASE_ADDRESS | pAddress;
   Address<<=1;

   i2c_start();
   i2c_write(Address);
   i2c_write(LM75_TEMP_REG);
   i2c_start();
   i2c_write(Address | 1);
   HiByte=i2c_read();
   LoByte=i2c_read(0);
   i2c_stop();

   Data=make16(HiByte,LoByte);
   Data>>=5; //lower 5 bits aren't used

   //test the sign bit
   if ((Data & 1024)==0) //temperature is positive, sign bit not set
   {
      Temperature=Data*0.125;
   }
   else //temperature is negative
   {
      Temperature=(0-Data)*0.125;
   }

   return(Temperature);
}


void main()
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(VREF_LOW|-2);

   printf("Temp is %f(C)\r\n",LM75_ReadTemperatureRegister(0));
   printf("Temp is %f(C)\r\n",LM75_ReadTemperatureRegister(1));
}


Note my #use i2c() statement is slightly different as this program I have been running on my breadboard/test platform. Although my project uses a different PIC microcontroller it experiences the same results.

All I change when running this program is the A0 pin on the LM75. If I ground it the first printf() prints a valid temperature while the second doesn't (expected, only one LM75 on the bus). If I make A0 high neither statement prints out a valid temperature (expected for the first printf(), not the second).
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 3:07 pm     Reply with quote

The "%f" format specifier doesn't really work by itself, in many versions
of the compiler. You need to give it a width and a precision value.
Use something like "%3.2f" instead.

Also, you need a while(1); statement right before the closing brace of
main(). If you don't have it, the PIC will execute a hidden SLEEP
instruction and cut off the last two characters that are sent to the
hardware UART.

Also, the setup_vref() statement is wrong. There is no "-2" parameter.
The PCWH wizard has a bug. I would just delete that whole statement.
The Vref generator is disabled upon reset, anyway.
jleblanc



Joined: 17 May 2006
Posts: 9

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 3:20 pm     Reply with quote

Made those changes; same results.

Thanks a lot for the help/pointers by the way. It is much appreciated.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 3:22 pm     Reply with quote

From looking at the spec. sheet it seems as though the base address(lowest) would be 0x90. You have assigned the variable, LM75_BASE_ADDRESS to a value of 72 which is HEX 0x48. The possible addresses are 0x90(A0,A1,A2=low), 0x92, 0x94, 0x96 and so on up to 0x9E. I have no idea what address you are sending to the routine as pADDRESS but make sure it ends up to be one of 0x90 to 0x9E.

Also, when declaring a double does that make it signed or unsigned. If you want to be returning a negative number you will want to make sure that it is signed.

Ronald
jleblanc



Joined: 17 May 2006
Posts: 9

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 3:29 pm     Reply with quote

Quote:
From looking at the spec. sheet it seems as though the base address(lowest) would be 0x90. You have assigned the variable, LM75_BASE_ADDRESS to a value of 72 which is HEX 0x48. The possible addresses are 0x90(A0,A1,A2=low), 0x92, 0x94, 0x96 and so on up to 0x9E. I have no idea what address you are sending to the routine as pADDRESS but make sure it ends up to be one of 0x90 to 0x9E.


The base address actually is 72 decimal; however because the address is only 7 bits the last bit in the address transmission (LSB) is the write flag. You'll notice in my code that I shift my address variable left one bit to take this into account. So the actual addresses being transmitted are correct.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 3:41 pm     Reply with quote

1. Remove the first LM75 chip from the bus, physically, so that only
the 2nd chip is present.

2. Hardcode your program to talk to the 2nd LM75 only.
Hardcode the addresses.

See if that works.
jleblanc



Joined: 17 May 2006
Posts: 9

View user's profile Send private message

PostPosted: Tue Aug 01, 2006 4:06 pm     Reply with quote

Quote:
1. Remove the first LM75 chip from the bus, physically, so that only
the 2nd chip is present.


All of my tests have been conducted with a single LM75 which I just change pin A0 on. There have not been two LM75's on my test board simultaneously for any of my tests.

Quote:
2. Hardcode your program to talk to the 2nd LM75 only.
Hardcode the addresses.


This fixed the problem but not directly. It still didn't work with hard coded addresses so I thought I'd better inspect my hardware again and make sure I didn't overlook something. Turns out I had. Pin placement created an island in my ground plane which was supposed to ground the A1 & A2 address pins leaving them floating. Added a jumper wire to actually ground them and now my code works fine.

So thanks for the help and for pointing out other mistakes in my code.
claude
Guest







building a project for loggin temperature
PostPosted: Sun Nov 19, 2006 11:20 am     Reply with quote

How much distance can i get bi using a lm75 , i mean how far from the pic can i put it. I'm pplanning of making a 24 lm75 sensor logging pic program, that will outpus the temperatures over 232, and add the them into nice draw....is it possible to put them as far as 5 meters ? i have made this program , and it work, i managed to get the data on a lcd whit 1*16 characters.
My question is what must i change to be able to use more lm 75's by them adresses ? A0A1A2

#include <16F870.h>
#use delay(clock=4000000)
#fuses XT,NOWDT,PUT,NOPROTECT,BROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#define SDA_PIN PIN_C2 // i2c serial data in/out
#define SCL_PIN PIN_C3 // i2c serial clock
// Variabile pentru citire LM75
int8 dataH,dataL,current_temp, max_temp, min_temp;
int1 flgSign;
char txt;
#define p1 PIN_A3 //push button for temperature reset
#define p4 PIN_A0
#define buz PIN_A4 //buzzer
#define fan PIN_A5
#use i2c(master,sda=SDA_PIN, scl=SCL_PIN)
void i2c_init(void)
{
output_high( SCL_PIN );
output_high( SDA_PIN );
}

void lm75_start(void)
{
i2c_start();
i2c_write(0x90);
i2c_write(0x01); // Pointer Byte
i2c_write(0x00); // Configuration Byte (operating)
i2c_stop();
}

void lm75_setandread(void)
{
i2c_start();
i2c_write(0x90);
i2c_write(0x00); // Pointer Byte
i2c_start();
i2c_write(0x91);
dataH = i2c_read(); // with ACK
dataL = i2c_read(0); // with NOACK
// dataL &= 0x80; // // D6-D0 sunt undefined
i2c_stop();
}
#include <lcdme.c>

void sounds() {
output_low(buz);delay_ms(20);
output_high(buz);delay_ms(20);
output_low(buz);delay_ms(30);
output_high(buz);delay_ms(30);
output_low(buz);delay_ms(40);
output_high(buz);delay_ms(40);
output_low(buz);delay_ms(50);
output_high(buz);delay_ms(50);
output_low(fan);
}
void reset_temp() {

current_temp = dataH;
min_temp=current_temp;
max_temp=current_temp;
}

main() {

i2c_init();
delay_ms( 10 );
lcd_init();
reset_temp();
txt=223;
while(1)

{

lm75_start();
delay_ms( 30 );
// lm75_read();
lm75_setandread();
// lm75_shutdown();
delay_ms( 100 );

// Stabileste valoarea/semnul temperaturii (in 0,5 grade Celsius)
flgSign = 0;
if( bit_test( dataH, 7 ) ){ // semn negativ (bit-ul 7 setat)
flgSign = 1;
dataH = ( 0xFF - dataH + 1 );
}
dataH = ( dataH <<1>max_temp) max_temp=current_temp;
else if(current_temp<min_temp>=27) sounds();
else {output_high(buz);output_high(fan);}
lcd_gotoxy(1,1);
printf(lcd_putc,"%u %cC" ,min_temp,txt);
lcd_gotoxy(6,1);
printf(lcd_putc,">%u" ,dataH);
lcd_gotoxy(1,2);
printf(lcd_putc,"< %u %cC" ,max_temp,txt);

if (!input(p4)) {lcd_gotoxy(1,1);printf(lcd_putc, "Claudiu ");
lcd_gotoxy(1,2);printf(lcd_putc, "Godinel ");
output_high(buz);}

delay_ms(250);
}}
godinel claudiu
Guest







a program to talk to several lm 75's
PostPosted: Wed Mar 21, 2007 1:17 am     Reply with quote

#include <16F870.h>
#use delay(clock=4000000)
#fuses XT,NOWDT,PUT,NOPROTECT,BROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#define SDA_PIN PIN_C2 // i2c serial data in/out
#define SCL_PIN PIN_C3 // i2c serial clock
#define p1 PIN_A3
#define LM75_WRITE1 0x90 // 1001 0000
#define LM75_READ1 0x91 // 1001 0001
#define LM75_WRITE2 0x9e // 1001 1110
#define LM75_READ2 0x9f // 1001 1111

#use i2c(master,sda=SDA_PIN, scl=SCL_PIN)
int8 dataH,dataL,temp,senz,x;
int1 flgSign;
char grad;

void i2c_init(void)
{
output_high( SCL_PIN );
output_high( SDA_PIN );
}


void lm75_start(int8 x)
{
i2c_start();
if (x==1) i2c_write(LM75_WRITE1);
else i2c_write(LM75_WRITE2);
i2c_write(0x01); // Pointer Byte
i2c_write(0x00); // Configuration Byte (operating)
i2c_stop();
}

void lm75_setandread(int8 x)
{
i2c_start();
if (x==1) i2c_write(LM75_WRITE1);
else i2c_write(LM75_WRITE2);
i2c_write(0x00); // Pointer Byte
i2c_start();
if (x==1) i2c_write(LM75_READ1);
else i2c_write(LM75_READ2);
dataH = i2c_read(); // with ACK
dataL = i2c_read(0); // with NOACK
i2c_stop();
}

#include <lcdme.c>

main() {

i2c_init();
delay_ms( 10 );
lcd_init();
senz=1;
grad=223;

while(1)
{

lcd_gotoxy(1,1);
printf(lcd_putc,"Senz");
lcd_gotoxy(6,1);
printf(lcd_putc,"%u =",senz);

lm75_start(senz);
delay_ms( 30 );
lm75_setandread(senz);
//lm75_shutdown();
delay_ms( 100 );

// Stabileste valoarea/semnul temperaturii (in 0,5 grade Celsius)
flgSign = 0;
if( bit_test( dataH, 7 ) ){ // semn negativ (bit-ul 7 setat)
flgSign = 1;
dataH = ( 0xFF - dataH + 1 );
}
dataH = ( dataH << 1 );
if( bit_test( dataL, 7 ) ) // 0,5 grade (bit-ul 7 setat)
dataH |= 0x01;
//facut de Godinel claudiu
// Ajusteaza valoarea temperaturii (cu +2 grade) (4 unitati de 0,5 grade)
if (senz==1) dataH -= 25 ;
if (senz==2) dataH -= 33 ;
dataL += 128 ;
temp=dataH;

lcd_gotoxy(1,2);
printf(lcd_putc,"Tmp");
lcd_gotoxy(5,2);
printf(lcd_putc,"%u" ,dataH);
lcd_gotoxy(7,2);
printf(lcd_putc,"%cC",grad);
if (!input(p1)) {senz=senz+1; if(senz==3) senz=1;}
delay_ms(100);

//if (!input(p4)) {lcd_gotoxy(1,1);printf(lcd_putc, "Claudiu ");
//lcd_gotoxy(1,2);printf(lcd_putc, "Godinel ");
//output_high(buz);}
}}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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