Menu

Can't get reading below 32 degrees F to properly display with a SI7021 Temp/Humid Sensor

Help
Ben Omlor
2023-05-25
2023-05-31
  • Ben Omlor

    Ben Omlor - 2023-05-25

    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

     
  • Anobium

    Anobium - 2023-05-25

    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 ?

     
  • Ben Omlor

    Ben Omlor - 2023-05-25

    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!

     
  • Ben Omlor

    Ben Omlor - 2023-05-25

    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

        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

    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

     
  • Anobium

    Anobium - 2023-05-26

    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,

     
  • Ben Omlor

    Ben Omlor - 2023-05-26

    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!

     
  • Anobium

    Anobium - 2023-05-26

    Great to hear!

    Post a working program (as an attachment) and I will lift into a demo. Thanks.

     
  • Ben Omlor

    Ben Omlor - 2023-05-26

    Working program attached.

     
  • Anobium

    Anobium - 2023-05-30

    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
  • Ben Omlor

    Ben Omlor - 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:-)

     
    • Anobium

      Anobium - 2023-05-30

      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
  • Anobium

    Anobium - 2023-05-31

    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:

    '' -------------------PORTA----------------
    '' Bit#:  -7---6---5---4---3---2---1---0---
    '' IO:    --------------------EN---------
    ''-----------------------------------------
    ''
    
    '' -------------------PORTB----------------
    '' Bit#:  -7---6---5---4---3---2---1---0---
    '' IO:    SDA-DB7-DB6-DB5---
    ''-----------------------------------------
    ''
    
    '' ------------------PORTC-----------------
    '' Bit#:  -7---6---5---4---3---2---1---0---
    '' IO:    ----------------SCL-DB4--RS--TX--
    ''-----------------------------------------
    ''
    
    '' ------------------PORTE-----------------
    '' Bit#:  -7---6---5---4---3---2---1---0---
    '' IO:    ----------------RST--------------
    ''-----------------------------------------
    ''
    

    Enjoy

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.