wangine
Joined: 07 Jul 2009 Posts: 98 Location: Curtea de Arges, Romania
|
Read temperature & humidity for SHT25, SHT21 sensor |
Posted: Sat Sep 12, 2015 10:12 am |
|
|
The code was tested in a real hardware and simulated as well with 4 different sensors SHT21&SHT25 include (Chinese sensors). Code was tested in special chamber around other 3 home made hardware and 2 industrial calibrated devices for comparison.
Code don't have dependence of I2C port, can be use any pins. Range of OSC where has been tested is 4, 8 and 16MHz.
Single issue of code have a +0.02 error on humidity, example On 40.60 real humidity will show 40.00 humidity, but on 40.50 will show 40.52, that's it not a big deal, the sensor it self don't have that accuracy, but the idea is to don't put more errors in as code. Also i notice, SHT25 is more faster and accurate than SHT75 sensor, even the technical data look almost the same. The data line has tested above 1 meter, with decouple 100n cap on the end.
Code: | #include <18F4550.h>
#device ADC=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
//#use fast_io(B)
//#use delay(internal=8MHz)
//#USE RS232
//#use standard_io(B)
#use delay(crystal=8MHz)
extern void lcd_gotoxy(int8 x, int8 y);
extern void lcd_putc(char c); |
SHT2x driver
Code: | /********************************************************************/
/* Writer Tanase Bogdan */
/* (c) copyright www.wangine.ro */
/* ALL RIGHTS RESERVED */
/* */
/********************************************************************/
/* Ver 0.6 release 10/september/2015 */
/********************************************************************/
/*Code will work with 4,8 and 16MHz oscillator, not tested above 16MHx*/
/*require pull up resistor 10k, on SDA/SCL line */
/********************************************************************/
//~~~~~~~~~~~~define I2C custom port~~~~~~~~~~~~~~~~~~~~~
#define sda_pin PIN_B0
#define scl_pin PIN_B1
//IIC
/*****************************Macro definition*****************************/
#define SCL_H output_high(scl_pin)
#define SCL_L output_low(scl_pin)
#define SDA_H output_high(sda_pin)
#define SDA_L output_low(sda_pin)
#define SCL_out output_drive(scl_pin) //Output Clock
#define SDA_in output_high(sda_pin) //SDA change the input mode
#define SDA_out output_drive(sda_pin) //SDA output mode back
#define SDA_val input_state(sda_pin) //Bit value of SDA
#define ACK 0 //Reply
#define NACK 1 //Non-responders
#define SHT21ADDR 0x80
#define humid_comand 0xF5 // command reading humidity
#define temp_comand 0xF3 // command reading temperature
#define REG_wait 120
#define calibration 0.996018f
float temperature = 0; // global temp variable
float humidity = 0; // global humid variable
/*****************************************************************
[Function name] Start
[Function] to complete the operation starting condition IIC
[Parameters None
[Return value None
*****************************************************************/
void Start(void)
{
SCL_out;
SDA_out;
SDA_H;
SCL_H;
delay_us(10);
SDA_L;
delay_us(10);
SCL_L;
delay_us(10);
}
/*****************************************************************
[Function name] Stop
[Function] to complete the operation termination condition IIC
[Parameters None
[Return value None
*****************************************************************/
void Stop(void)
{
SCL_out;
SDA_out;
SCL_L;
delay_us(10);
SDA_L;
delay_us(10);
SDA_H;
delay_us(10);
SCL_H;
delay_us(10);
}
/*****************************************************************
[Function name] Mack
[Function] to complete IIC host response operations
[Parameters None
[Return value None
*****************************************************************/
void Mack(void)
{
SCL_out;
SDA_out;
SDA_L;
delay_us(2);
SCL_H;
delay_us(10);
SCL_L;
delay_us(10);
SDA_H;
delay_us(10);
}
/*****************************************************************
[Function name] MNack
[Function] to complete non-response operations IIC hosts
[Parameters None
[Return value None
*****************************************************************/
void MNack(void)
{
SCL_out;
SDA_out;
SDA_H;
delay_us(2);
SCL_H;
delay_us(10);
SCL_L;
delay_us(2);
SDA_L;
delay_us(10);
}
/*****************************************************************
[Function name] Check
[Function] check from the answering machine's operation, 1-- there, no 0--
[Parameters None
[Return Value] ACK (acknowledge) or NACK (not acknowledge)
*****************************************************************/
unsigned char Check(void)
{
int1 ack_q;
SCL_out;
SDA_out;
SDA_H;
delay_us(2);
SCL_H;
delay_us(2);
SDA_in;
delay_us(2);
ack_q = SDA_val; //??SDA??
SCL_L;
delay_us(10);
SDA_out;
if(ack_q) return NACK;//1:???
else return ACK;
}
/*****************************************************************
[Function name] Write1
[Function] IIC bus sends a 1
[Parameters None
[Return value None
*****************************************************************/
void Write1(void)
{
SCL_out;
SDA_out;
SCL_L;
delay_us(10);
SDA_H;
delay_us(2);
SCL_H;
delay_us(10);
SCL_L;
delay_us(10);
}
/*****************************************************************
[Function name] Write0
[Function] sending a 0 to the IIC bus
[Parameters None
[Return value None
*****************************************************************/
void Write0(void)
{
SCL_out;
SDA_out;
SCL_L;
delay_us(10);
SDA_L;
delay_us(2);
SCL_H;
delay_us(10);
SCL_L;
delay_us(10);
}
/*****************************************************************
[Function name] WriteByte
[Function] to send a byte to the IIC bus
[Parameters] wdata for the data to be written
[Return Value] respond to the response signal returned from the machine
*****************************************************************/
unsigned char WriteByte(unsigned char wdata)
{
unsigned char i,respond;
SCL_out;
SDA_out;
for(i = 8;i > 0;i--)
{
if(wdata & 0x80)
Write1();
else
Write0();
wdata <<= 1;
}
SDA_H;
delay_us(10);//_NOP();
respond = Check();
return respond;
}
/*****************************************************************
[Function name] ReadByte
[Function] to read a byte from the IIC bus
[Parameters None
[Return Value] rdata to read data
*****************************************************************/
unsigned char ReadByte(void)
{
unsigned char rdata = 0x01,i;
int1 flag;
SCL_out;
//SDA_out;
for(i = 0;i < 8;i++)
{
SDA_H;
delay_us(2);//Delay();
SCL_H;
SDA_in;
delay_us(10);//Delay();
flag = SDA_val;
rdata <<= 1;
if(flag)
{
rdata |= 0x01;
}
SDA_out;
SCL_L;
delay_us(10);//Delay();
}
return rdata;
}
/*****************************************************************
[Function name] Read_temp and Read_humid
[Function] Sht21 measurement of temperature and humidity
Parameters 0xf3 measured temperature; 0xf5 measuring humidity
[Return Value] temperature, humidity
*****************************************************************/
void read_temp()
{
float temp = 0;
float T = 0;
unsigned int8 MSB,LSB;
Start();
if(WriteByte(SHT21ADDR & 0xfe) == ACK)
{
if(WriteByte(temp_comand) == ACK)
{
do
{
delay_ms(REG_wait);
Start();
}
while(WriteByte(SHT21ADDR | 0x01) == NACK);
Stop();
MSB = ReadByte();
Mack();//IIC host response operations
LSB = ReadByte();
MNack();//IIC host non-response operation
LSB &= 0xfc;// Two status bits, front and rear, LSB is conducting two physical computing must be set to '0'
temp = MSB*256+LSB;
T=0.26813*temp-4685;//TH=(175.72)*temp/65536.0-46.85;
temperature = T / 100;
}
}
}
//********************************************************************
void read_humid()
{
float temp = 0;
float H = 0;
unsigned int8 MSB,LSB;
Start();
if(WriteByte(SHT21ADDR & 0xfe) == ACK)
{
if(WriteByte(humid_comand) == ACK)
{
do
{
delay_ms(REG_wait);
Start();
}
while(WriteByte(SHT21ADDR | 0x01) == NACK);
Stop();
MSB = ReadByte();
Mack();//IIC host response operations
LSB = ReadByte();
MNack();//IIC host non-response operation
LSB &= 0xfc;// Two status bits, front and rear, LSB is conducting two physical computing must be set to '0'
temp = MSB*256+LSB;
H = temp/65536.0 ;//0xC89F;
humidity = (H * 125) - 6.50f ;
humidity *= calibration;
// humidity = (long int)(H*100)/100;//H =0.190735*temp-600;//TH = (temp*125.0)/65536.0-6;
}
}
}
//***************************************************************************** |
and example how to use
Code: | #include <main4550.h>
#include <math.h>
#include </src/flex_lcd_20x2.c>
#include </src/__SHT21.c>
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int1 flag_sht = 1;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#INT_RTCC
void RTCC_isr(void)
{
WriteByte(0xFE); // in case if comunication is lost
if(flag_sht == true)
{
read_temp();
flag_sht = false;
}
else
{
read_humid();
flag_sht = true;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void main ()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); //262 ms overflow
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lcd_init(); // Always call this first.
delay_ms(10); // Minimum 1 ms required after power-up.
while (true)
{
// read_temp();
lcd_gotoxy(1,1);
printf(lcd_putc, "temperatura:%3.2f gC ", temperature );
// read_humid();
lcd_gotoxy(1,2);
printf(lcd_putc, "umiditate :%3.2f RH ", humidity );
}
} |
|
|