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

SHT45 & SHT85 Humidity / Temp Sensors with PIC16F88

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



Joined: 13 Jul 2023
Posts: 37

View user's profile Send private message

SHT45 & SHT85 Humidity / Temp Sensors with PIC16F88
PostPosted: Thu Jul 13, 2023 12:52 am     Reply with quote

Hello dear friends,

I am working on a project that will communicate with PIC16F88 both sht45 and sht85 over i2c. As a result of my research for a long time, I saw that I could create software over the most suitable CCS C in the PIC model I mentioned. However, I could not create the i2c code of the PIC. I also checked the datasheets of the sensors, but since I only use the i2c protocol over the arduino, I could not understand the protocol I need to do. I found some sample codes and modified them according to myself and brought it to a point. I confirmed with the "get_ack_status" function that there is a device at address 0x88, but unfortunately I still cannot communicate with the sensor. Since I don't have a serial port or a screen to show the incoming data at the moment, I am testing the program with a more primitive led on and off method. I am sharing the code I wrote below, it would be very helpful if you could review my mistakes and tell me how to fix them.

Code:


Code:

#include <16F88.h>
#include <main.h>
#fuses NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=4000000)
#use i2c(Master, sda=PIN_B1, scl=PIN_B4)
#use FIXED_IO(A_outputs=PIN_A2,PIN_A3)

#define SHT85_BASE_ADDR  0x88
unsigned int8 wData[1] = SHT45_CMD_MEASURE_HPM;
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()
{

status = get_ack_status(0x88);

while(TRUE)
{       
        i2c_start();
        i2c_write(SHT85_BASE_ADDR); 
        i2c_write(0x24); 
        i2c_write(0x0B);
        i2c_stop();
       
        delay_ms(15); 
        i2c_start();
        i2c_write(SHT85_BASE_ADDR | 0x01); 
        float temperature_humidity_raw = make16(i2c_read(), i2c_read());
        i2c_read();  // CRC verisini oku ve geƧ
        i2c_stop();
        float temperature = -45.0 + 175.0 * (float)temperature_humidity_raw / 65535.0;
        float humidity = 100.0 * (float)temperature_humidity_raw / 65535.0;
        delay_ms(1000); 
        if (temperature > 30.0)
        {
         output_high(PIN_A2);
         output_low(PIN_A3);
        }
        else
        {
         output_high(PIN_A3);
         output_low(PIN_A2);
        }
}
}






[/code]
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Jul 13, 2023 2:38 am     Reply with quote

Several of the things that might be problems you have already covered
by using get_ack_status.
I would be worried though that the two read calls may not execute left
to right in C. C does not guarantee the order of function parameter calls.
Try simply reading the two values one after the other, and then use a
separate make8 call.
Why are you sending a second byte after the 0x24 command?. The chip
does not want this. It shows all commands as being 8bits only.
The chip returns the reading after 0.1 second. You need a longer delay
after sending the command.
Code:

byte valh, vall;
int16 temperature_raw

while(TRUE)
{       
        i2c_start();
        i2c_write(SHT85_BASE_ADDR);
        i2c_write(0x24); //command 0.1sec then return vals
        i2c_stop();       
        delay_ms(105); //Allow 0.1sec plus margin

        i2c_start();
        i2c_write(SHT85_BASE_ADDR | 0x01);
        valh=i2c_read(); //MSB
        vall= i2c_read(); //LSB
        temperature_raw = make16(valh, vall);
        vall=i2c_read(); 
        valh=I2c_read();
        valh=I2c_read();
        valh=i2c_read(); //dummy read of humidity bytes
        i2c_stop();
        float temperature = -45.0 + 175.0 * (temperature_raw / 65535.0);
        delay_ms(1000);
        if (temperature > 30.0)
        {
         output_high(PIN_A2);
         output_low(PIN_A3);
        }
        else
        {
         output_high(PIN_A3);
         output_low(PIN_A2);
        }
}
}

Now I note that the data sheet says you can abort the command after
reading the 16bit value, without reading the CRC, but it does not at
any point talk about aborting after reading the temperature without
reading the humidity, which is what you are doing. I'd say it'd be
worth trying reading all six bytes. I show that above.
You don't need the casts. dividing by 65535.0 (a float value), forces
float arithmetic.

There is one major hardware issue you may have. The Arduino accepts
+2.4v as a 'high' for a signal. On your 5v PIC the signals have to go up
to just on 4v to be correctly seen as high. You could try wiring to a pair
of pins that support TTL inputs, and using software I2C. Pins A0/A1 for example.
temtronic



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

View user's profile Send private message

PostPosted: Thu Jul 13, 2023 5:21 am     Reply with quote

Mr T's last paragraph was the 1st thing I thought of....
5 volt PIC, 3 volt peripheral issue....
Nowadays ,it'd probably be best to use a 3 volt PIC as 99.44% of all peripherals are 3 volt devices.
Also, the I2C pullups generally should be 4k7 for 5 volt, 3k3 for 3 volt. The peripheral, if it's a 'module' may or may not have pullups so best to check and measure.
bmete



Joined: 13 Jul 2023
Posts: 37

View user's profile Send private message

PostPosted: Thu Jul 13, 2023 5:35 am     Reply with quote

Thank you very much for your quick reply my friend. I run the code and it works great. Actually I also need a humidity value so I am going to add it. But I just wanted to learn how to receive data from sensor.

So I modified the code for SHT45 to receive both humidity and temperature data. I checked the code and it looks like works good.

Code:

i2c_start();
        i2c_write(SHT45_BASE_ADDR);
        i2c_write(0xFD); //command 0.1sec then return vals
        i2c_stop();       
        delay_ms(105); //Allow 0.1sec plus margin

        i2c_start();
        i2c_write(SHT45_BASE_ADDR | 0x01);
        valh = i2c_read(); //MSB
        vall = i2c_read(); //LSB
        temperature_raw = make16(valh, vall);
        CRC = i2c_read();
        valh = i2c_read();
        vall = I2c_read();
        humidity_raw = make16(valh, vall);
        CRC = i2c_read(); //dummy read of humidity bytes
        i2c_stop();
        float temperature = -45.0 + 175.0 * (temperature_raw / 65535.0);
        float humidity = -6.0 + 125.0 * (humidity_raw / 65535.0);



Quote:

There is one major hardware issue you may have. The Arduino accepts
+2.4v as a 'high' for a signal. On your 5v PIC the signals have to go up
to just on 4v to be correctly seen as high. You could try wiring to a pair
of pins support TTL inputs, and using software I2C. Pins A0/A1 for example.


I'm thinking of a hardware design similar to what you said, but how do I configure the A0 and A1 pins to receive data from i2c as software?
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Jul 13, 2023 7:56 am     Reply with quote

#USE_I2C will automatically setup and use software I2C, if you tell it to
use pins that don't have the hardware.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 13, 2023 11:03 am     Reply with quote

According to the SHT85 datasheet, you're supposed to do a NACK after the
last i2c_read() statement. This is done by giving i2c_read() a parameter of 0.
Example: i2c_read(0);

On page 10 of the data sheet it says:
Quote:
The sensor will send the temperature value first and then the relative
humidity value. After having received the checksum for the humidity
value a NACK and stop condition should be sent (see Table8).

SHT85 datasheet:
https://www.sensirion.com/media/documents/4B40CEF3/61642381/Sensirion_Humidity_Sensors_SHT85_Datasheet.pdf
bmete



Joined: 13 Jul 2023
Posts: 37

View user's profile Send private message

PostPosted: Fri Jul 14, 2023 12:46 am     Reply with quote

Thank you for all your help.

I think I understood the procedure for reading data from sensors. Apart from that, there is one more thing I want to ask you. The card with 16f88 and the sensor will send the data it read from the sensor to the PIC on the other card via i2c in line with the message from another card. In this case, 16f88 will be the master for the sensor but the slave for the other PIC. How can I configure in such a case? Can I set the same chip as both master and slave? I guess I need to use Interrupt to wait for a message over I2C. It would be very helpful if you could give me a short example of the procedure for this or tell me which of the ready-made examples I can use.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Fri Jul 14, 2023 1:03 am     Reply with quote

No.
You will need to have two I2C busses. Use the hardware one for the slave.
(It is almost impossible to do a slave in software). Use a second software
I2C as master to talk to the chip.
There is a technical version of I2c (multi master), where more than one
master device can exist on a bus, your chip does not support this,
but even on this the same device cannot be a master and a slave.

I honestly have to repeat my suggestion on going to a newer PIC. The 88, is
very old chip, and lacks performance compared to newer devices. Many
will offer multiple I2C busses, and these would be much better. Also
more RAM and ROM (you will soon run out of space doing floating point
maths for this).
bmete



Joined: 13 Jul 2023
Posts: 37

View user's profile Send private message

PostPosted: Tue Jul 18, 2023 12:27 am     Reply with quote

Thanks for all of your help guys. Now I need to do same procedure on HDC3022. I tried so many different things but there was no positive result. For this purpose can we argue this in this topic? Or do I need to open a new Topic for this?
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Tue Jul 18, 2023 2:20 am     Reply with quote

The 3022, needs a two byte command, not the single byte for the SHT
Very different beasty. 24 00, not FD....
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