I am working on a project using a SI7021 Temp/Humidity Sensor.
I have her all working with the help of some demo code I found searching the forum.
The issue I am having is it will not properly display temps below 32F
I believe it is a math issue dealing with negative numbers converting from C to F.
Here is the math code.
I have TemperatureC and TemperatureF DIM'ed as Integer
If I change the [Long] in the equation to integer the display stays stuck at 78.6 and does not change.
As written it works great unit the temp get below 32.
I would normally collate code resources from the forum and change into a Demo. In this case I have not. This may may mean I missed it, or I was converned ergarding the approach or documentation.
Also, what is the range ( raw ) off SiRaw ?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
'One Second timer
If Cntr >= 4 then '1 seconds has elapsed
Cntr = 0
Call Read_Humidity
Call Read_Temperature
End if
End Sub
Sub Read_Humidity
Hi2CStart
HI2CSend (0x80) 'Write
Hi2cSend (0xF5)
Hi2CReStart
HI2CSend (0x81) 'read
wait 50 ms ' for conversion ( could be less)
Hi2CReStart
I just reviewed the original post. I had my doubts about the maths but did not get a response.
I am not able to do any testing on this but here are my thoughts.
TemperatureC is the key. Ignore everything else until this works as expected. TemperatureC is an integer so that is ok,
Put a series of value thru the TemperatureC calc like 0 to 0xFFFF,,, what are the results ? So, dont do the IC2 read as the series of values could be a For Next Loop. Do these value range from -10 to 80,
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks!
That was a great idea to break it down!
Problem was when the temp c was calculated it was x 100 to get rid of the decimals.
So 50 DegreesC was represented as 5,000.
When tempF was changed to integer and the tempC was fed into the formula it took the answer out of the integer limits of 32767.
Answer was to divide tempC by 10 before calculating for temp F. to stay in the integer range, and change tempF calculations to a factor of 10 instead of 100.
Working Math is:
TemperatureC = (([long]SiRaw * 17572) / 65536) - 4685
TemperatureC = TemperatureC / 10
TemperatureF = (([integer]TemperatureC * 9) /5) + 320
I have taken you code and changed to a demo that we can include.
Try it, Make any changes but I have changed the Subs to return the values required for processing on the LCD ( which means the Subs just read the value making it a lot easier to change the output method to serial etc.)
Let me know what needs to be changed. I will update the comments etc when I get you validated code back!
Thank you.
This demo has been tested. It shows the great capabilites of the Si7021 sensor.
Hello,
I have tried the code. The only gotchas for my set up was removing the // before the #DEFINE USE_LCD to make that active and then adding ' before :
'#IFDEF USE_SERIAL
'Show message on Serial Terminal
'HserPrintCRLF 2
'HSerPrint "HUMD"
'HserSend 9
'HSerPrintStringCRLF "TMP"
'#ENDIF
Once I remove the // on the define use_lcd line it would not asm until I greened out the USE_Serial Section.
Based on the notes I assume that this is the way it is supposed to work to make the program more versatile for I2C and Serial.
With those changes she worked perfectly!
Thanks again:-)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is a demonstration for the Si7021 breakout board..
These sensors use I2C to communicate, 2 pins are required to interface. Silicon labs has ± 3% relative humidity measurements with a range of 0–80% RH, and ±0.4 °C temperature accuracy at a range of -10 to +85 °C. Great for all of your environmental sensing projects. It uses I2C for data transfer so it works with a wide range of microcontrollers.
The Si7021 is a I2C sensor. That means it uses the two I2C data/clock wires available on most microcontrollers, and can share those pins with other sensors as long as they do not have an address collision. The default I2C address is 0x80.
The defaults used in this demonstration are:
Software I2C ( therefore PPS is not required [ if you examine InitPPS() then you will see a method to ensure PPS is not set when not using HardwareI2C])
LCD in 4bit is enabled - see the setup for the port.pin(s) used
LCD emulation to a serial terminal is disabled
Serial Terminal is enabled but you will have to set PPS for PPS chips. Serial Terminal BPS is 9600.
Connectivity:
Vin - this is the power pin. Since the chip uses 3 VDC, we have included a voltage regulator on board that will take 3-5VDC and safely convert it down. To power the board, give it the same power as the logic level of your microcontroller - e.g. for a 5V micro like Arduino, use 5V
GND - common ground for power and logic
I2C Logic pins:
SCL - I2C clock pin, connect to your microcontrollers I2C clock line.
SDA - I2C data pin, connect to your microcontrollers I2C data line.
Reading the sensor to the serial terminal looks like this with a reading every second
50% 28.8F -1.8C
50% 28.8F -1.8C
50% 28.8F -1.8C
50% 28.6F -1.9C
49% 28.6F -1.9C
49% 28.6F -1.9C
49% 28.4F -2.0C
49% 28.4F -2.0C
49% 28.3F -2.1C
49% 28.3F -2.1C
49% 28.1F -2.2C
49% 28.1F -2.2C
49% 28.1F -2.2C
49% 27.9F -2.3C
49% 27.9F -2.3C
49% 27.9F -2.3C
Usage:
Read_Humidity ( Humidity ) - return the Humidity as a byte value
Read_Temperature ( TemperatureC, TemperatureC_Hundredths, TemperatureF, TemperatureF_Hundredths ) - returns the temperature as Integer and a Byte for each scale.
The programs setups the I2C and Serial and/or LCD. If you use a PPS chip then you will need to set the PPS. You can use either/both LCD and Serial - just see the comments below.
Connect the sensor as shown in the port details below:
Hello,
I am working on a project using a SI7021 Temp/Humidity Sensor.
I have her all working with the help of some demo code I found searching the forum.
The issue I am having is it will not properly display temps below 32F
I believe it is a math issue dealing with negative numbers converting from C to F.
Here is the math code.
I have TemperatureC and TemperatureF DIM'ed as Integer
If I change the [Long] in the equation to integer the display stays stuck at 78.6 and does not change.
As written it works great unit the temp get below 32.
TemperatureC = (([long]SiRaw * 17572) / 65536) - 4685
TemperatureF = (([long]TemperatureC * 9) /5) + 3205
Hundredths = TemperatureF % 100 'Modulud Divide
TemperatureF = TemperatureF / 100
Thanks for any help or ideas,
Ben
Hello,
Can you post the link to the code in the forum ?
I would normally collate code resources from the forum and change into a Demo. In this case I have not. This may may mean I missed it, or I was converned ergarding the approach or documentation.
Also, what is the range ( raw ) off SiRaw ?
Hello,
Link to the demo code is:
https://sourceforge.net/p/gcbasic/discussion/629990/thread/319a2f8f/
SiRaw according to the data sheet is a 16-bit word returned by the Si7021
Thanks!
Here is my full code.
'test program for black max buddy'
chip 16f18345,16
config FEXTOSC = OFF, RSTOSC = HFINT32
#config MCLRE = ON, WDTE=OFF
#CONFIG BOREN = Off
option explicit
#include <lowlevel\hwi2c.h></lowlevel\hwi2c.h>
#startup InitPPS, 85
#define HI2C_DATA PORTB.7
#define HI2C_CLOCK PORTC.3
'set up lcd Display
'LCD 4 bit, no rw, no lat
'********
define LCD_IO 4 '4-bit mode
define LCD_NO_RW
'#define LCD_SLOW 'NEW DEFINE
define LCD_enable porta.2
define LCD_RS portc.1
define LCD_DB7 portb.6
define LCD_DB6 portb.5
define LCD_DB5 portb.4
define LCD_DB4 portc.2
'I2C
hi2cMode Master
CLS
Dir hi2c_DATA in
Dir hi2c_CLOCK in
'Variables
Dim Si7021_HighByte, Si7021_LowByte as byte
Dim SiRaw Alias Si7021_HighByte, Si7021_LowByte as Word
Dim Humidity as Word
DIM Temperature as WORD
Dim Cntr as Byte 'each timer count is 250 ms
Dim Hundredths as Byte
Dim TemperatureC as integer
Dim TemperatureF as Integer
SiRaw = 0
cntr = 0
CLS
'Print Fixed locations
Locate 0,0
Print "TMP"
Locate 1,0
Print "HUMD"
'Setup 2 SecTimer
PR0 = 244 '// 250 ms
Inittimer0 (OSC, Pre0_32 + TMR0_LFINTOSC, 0)
Starttimer 0
On interrupt Timer0Overflow Call Counter_ISR
Main:
Do
'waiting for interrupt
Loop
sub Counter_ISR 'ISR
Cntr++ 'increment 250 ms counter
'One Second timer
If Cntr >= 4 then '1 seconds has elapsed
Cntr = 0
End if
End Sub
Sub Read_Humidity
Hi2CStart
HI2CSend (0x80) 'Write
Hi2cSend (0xF5)
Hi2CReStart
HI2CSend (0x81) 'read
wait 50 ms ' for conversion ( could be less)
Hi2CReStart
HI2CSend (0x81) 'read
Hi2CReceive (Si7021_HighByte, ACK)
Hi2CReceive (Si7021_Lowbyte, NACK)
Hi2Cstop
'now do the maths
Humidity = (([long]SiRaw * 125) / 65536) -6
Locate 1,5
If Humidity < 10 then Print "0"
Print Humidity : Print "%"
End Sub
Sub Read_Temperature
Hi2CStart
HI2CSend (0x80) 'Write
Hi2cSend (0xE0)
Hi2CReStart
HI2CSend (0x81) 'read
Hi2CReceive (Si7021_HighByte, ACK)
Hi2CReceive (Si7021_Lowbyte, NACK)
Hi2Cstop
wait 20 ms
TemperatureC = (([long]SiRaw * 17572) / 65536) - 4685
TemperatureF = (([long]TemperatureC * 9) /5) + 3205
Hundredths = TemperatureF % 100 'Modulud Divide
TemperatureF = TemperatureF / 100
Locate 0,4
Print TemperatureF : Print "." : Print Hundredths
End Sub
sub InitPPS
UNLOCKPPS
'Module: MSSP1
SSP1CLKPPS = 0x13 'RC2 > SCL1
RC3PPS = 0x18 'SCL1 > RC2 (bi-directional)
RB7PPS = 0x0019 'SDA1 > RC1
SSP1DATPPS = 0x00f 'RC1 > SDA1 (bi-directional)
LOCKPPS
End Sub
Thanks
I just reviewed the original post. I had my doubts about the maths but did not get a response.
I am not able to do any testing on this but here are my thoughts.
TemperatureC is the key. Ignore everything else until this works as expected. TemperatureC is an integer so that is ok,
Put a series of value thru the TemperatureC calc like 0 to 0xFFFF,,, what are the results ? So, dont do the IC2 read as the series of values could be a For Next Loop. Do these value range from -10 to 80,
Thanks!
That was a great idea to break it down!
Problem was when the temp c was calculated it was x 100 to get rid of the decimals.
So 50 DegreesC was represented as 5,000.
When tempF was changed to integer and the tempC was fed into the formula it took the answer out of the integer limits of 32767.
Answer was to divide tempC by 10 before calculating for temp F. to stay in the integer range, and change tempF calculations to a factor of 10 instead of 100.
Working Math is:
TemperatureC = (([long]SiRaw * 17572) / 65536) - 4685
TemperatureC = TemperatureC / 10
TemperatureF = (([integer]TemperatureC * 9) /5) + 320
Hundredths = TemperatureF % 10 'Modulud Divide
TemperatureF = TemperatureF / 10
Thanks Again!
Great to hear!
Post a working program (as an attachment) and I will lift into a demo. Thanks.
Working program attached.
Ben could you try the code attached.
I have taken you code and changed to a demo that we can include.
Try it, Make any changes but I have changed the Subs to return the values required for processing on the LCD ( which means the Subs just read the value making it a lot easier to change the output method to serial etc.)
Let me know what needs to be changed. I will update the comments etc when I get you validated code back!
Thank you.
This demo has been tested. It shows the great capabilites of the Si7021 sensor.
Last edit: Anobium 2023-05-30
Hello,
I have tried the code. The only gotchas for my set up was removing the // before the #DEFINE USE_LCD to make that active and then adding ' before :
'#IFDEF USE_SERIAL
'Show message on Serial Terminal
'HserPrintCRLF 2
'HSerPrint "HUMD"
'HserSend 9
'HSerPrintStringCRLF "TMP"
'#ENDIF
Once I remove the // on the define use_lcd line it would not asm until I greened out the USE_Serial Section.
Based on the notes I assume that this is the way it is supposed to work to make the program more versatile for I2C and Serial.
With those changes she worked perfectly!
Thanks again:-)
Excellent. I have moved to the demos. It is a good demo now.
I did take the sensor down to -18c... works OK. Nice little solution.
Thanks for your help!
Last edit: Anobium 2023-05-30
Demo: See it on GitHub
This is a demonstration for the Si7021 breakout board..
These sensors use I2C to communicate, 2 pins are required to interface. Silicon labs has ± 3% relative humidity measurements with a range of 0–80% RH, and ±0.4 °C temperature accuracy at a range of -10 to +85 °C. Great for all of your environmental sensing projects. It uses I2C for data transfer so it works with a wide range of microcontrollers.
The Si7021 is a I2C sensor. That means it uses the two I2C data/clock wires available on most microcontrollers, and can share those pins with other sensors as long as they do not have an address collision. The default I2C address is 0x80.
The defaults used in this demonstration are:
Software I2C ( therefore PPS is not required [ if you examine InitPPS() then you will see a method to ensure PPS is not set when not using HardwareI2C])
LCD in 4bit is enabled - see the setup for the port.pin(s) used
LCD emulation to a serial terminal is disabled
Serial Terminal is enabled but you will have to set PPS for PPS chips. Serial Terminal BPS is 9600.
Connectivity:
Vin - this is the power pin. Since the chip uses 3 VDC, we have included a voltage regulator on board that will take 3-5VDC and safely convert it down. To power the board, give it the same power as the logic level of your microcontroller - e.g. for a 5V micro like Arduino, use 5V
GND - common ground for power and logic
I2C Logic pins:
SCL - I2C clock pin, connect to your microcontrollers I2C clock line.
SDA - I2C data pin, connect to your microcontrollers I2C data line.
Reading the sensor to the serial terminal looks like this with a reading every second
50% 28.8F -1.8C
50% 28.8F -1.8C
50% 28.8F -1.8C
50% 28.6F -1.9C
49% 28.6F -1.9C
49% 28.6F -1.9C
49% 28.4F -2.0C
49% 28.4F -2.0C
49% 28.3F -2.1C
49% 28.3F -2.1C
49% 28.1F -2.2C
49% 28.1F -2.2C
49% 28.1F -2.2C
49% 27.9F -2.3C
49% 27.9F -2.3C
49% 27.9F -2.3C
Usage:
Read_Humidity ( Humidity ) - return the Humidity as a byte value
Read_Temperature ( TemperatureC, TemperatureC_Hundredths, TemperatureF, TemperatureF_Hundredths ) - returns the temperature as Integer and a Byte for each scale.
The programs setups the I2C and Serial and/or LCD. If you use a PPS chip then you will need to set the PPS. You can use either/both LCD and Serial - just see the comments below.
Connect the sensor as shown in the port details below:
Enjoy