News:

;) This forum is the property of Proton software developers

Main Menu

AHT20 Humidity & temperature sensor

Started by RGV250, Mar 13, 2021, 08:19 PM

Previous topic - Next topic

RGV250

Code for AHT20 and DS3231 clock sending serial output on 24HJ128GP502.

Main code.
'****************************************************************
'*  Name    : 24_AHT20.BAS                                      *
'*  Author  : Bobby Garrett                                     *
'*  Date    : 13/03/2021                                        *
'*  Version : 1.0                                               *
'*  Notes   : AHT20 and DS3231 using 24 Bit PIC                 *
'****************************************************************

'Things to consider adding, check status bit / AHT20 soft reset.

'  ____/\\\\\\\\\_________/\\\\\\\\\\\\__/\\\________/\\\____/\\\\\\\\\_______/\\\\\\\\\\\\\\\______/\\\\\\\____       
'   __/\\\///////\\\_____/\\\//////////__\/\\\_______\/\\\__/\\\///////\\\____\/\\\///////////_____/\\\/////\\\__       
'    _\/\\\_____\/\\\____/\\\_____________\//\\\______/\\\__\///______\//\\\___\/\\\_______________/\\\____\//\\\_     
'     _\/\\\\\\\\\\\/____\/\\\____/\\\\\\\__\//\\\____/\\\_____________/\\\/____\/\\\\\\\\\\\\_____\/\\\_____\/\\\_     
'      _\/\\\//////\\\____\/\\\___\/////\\\___\//\\\__/\\\___________/\\\//______\////////////\\\___\/\\\_____\/\\\_   
'       _\/\\\____\//\\\___\/\\\_______\/\\\____\//\\\/\\\_________/\\\//____________________\//\\\__\/\\\_____\/\\\_   
'        _\/\\\_____\//\\\__\/\\\_______\/\\\_____\//\\\\\________/\\\/____________/\\\________\/\\\__\//\\\____/\\\__ 
'         _\/\\\______\//\\\_\//\\\\\\\\\\\\/_______\//\\\________/\\\\\\\\\\\\\\\_\//\\\\\\\\\\\\\/____\///\\\\\\\/___
'          _\///________\///___\////////////__________\///________\///////////////___\/////////////________\///////_____


Device = 24HJ128GP502
Declare Xtal = 79.23

' Configure for internal 7.37MHz oscillator with PLL
' OSC pins are general purpose I/O
    Config FBS = BWRP_WRPROTECT_OFF
    Config FSS = SWRP_WRPROTECT_OFF
    Config FGS = GWRP_OFF
    Config FOSCSEL = FNOSC_FRCPLL, IESO_OFF
    Config FOSC = POSCMD_NONE, OSCIOFNC_ON, IOL1WAY_OFF, FCKSM_CSECME
    Config FWDT = WDTPOST_PS256, WINDIS_OFF, FWDTEN_OFF
    Config FPOR = FPWRT_PWR128, ALTI2C_OFF
    Config FICD = ICS_PGD1, JTAGEN_OFF   
   
PLL_Setup(43, 2, 2, $0300)                  'Configure the Oscillator to operate the device at 79.23MHz

    Include "DS3231.inc"                    ' Load the DS3231 procedures into the program
   
'I2C port declarations
    Symbol SCL = PORTB.8                    ' Clock pin (Yellow)
    Symbol SDA = PORTB.9                    ' Data pin  (Blue)
   
    Symbol AHT_ADDR_READ = 0x71             'AHT default address & read
    Symbol AHT_ADDR_WRITE = 0x70            'AHT default address & write
    Symbol AHT_CMD_INIT = 0xBE              'Trigger reading command     
    Symbol AHT_CMD_TRIGGER = 0xAC           'Trigger reading command
    Symbol AHT_CMD_SOFT_RESET = 0xBA        'Trigger soft reset

    Dim Temperature_Temp As Dword
    Dim Temperature_Temp_B0 As Temperature_Temp.Byte0 'Alias unsigned Part1 to the low byte
    Dim Temperature_Temp_B1 As Temperature_Temp.Byte1 'Alias unsigned Part2 to the 2nd byte
    Dim Temperature_Temp_B2 As Temperature_Temp.Byte2 'Alias unsigned Part3 to the 3rd byte
    Dim Temperature_Temp_B3 As Temperature_Temp.Byte3 'Alias unsigned Part3 to the high (4th) byte   
    Dim Temperature As Float
   
    Dim Humidity_Temp As Dword
    Dim Humidity_Temp_B0 As Humidity_Temp.Byte0       'Alias unsigned Part1 to the low byte
    Dim Humidity_Temp_B1 As Humidity_Temp.Byte1       'Alias unsigned Part2 to the 2nd byte
    Dim Humidity_Temp_B2 As Humidity_Temp.Byte2       'Alias unsigned Part3 to the 3rd byte
    Dim Humidity_Temp_B3 As Humidity_Temp.Byte3       'Alias unsigned Part3 to the high (4th) byte   
    Dim Humidity As Float 

'    Dim AHT_Status As Byte                            'Same as Data_0
    Dim AHT_Data_0  As Byte                           '0 - Status
    Dim AHT_Data_1  As Byte                           '1 - Humidity
    Dim AHT_Data_2  As Byte                           '2 - Humidity
    Dim AHT_Data_3  As Byte                           '3 - Humidity / Temperature
    Dim AHT_Data_4  As Byte                           '4 - Temperature
    Dim AHT_Data_5  As Byte                           '5 - Temperature
    Dim AHT_Data_6  As Byte                           '6 - CRC (Not used)
   
    Dim AHT_CALL As Byte                    ' Counter so AHT20 is not called every cycle
   
' USART2 declares
    Declare Hserial2_Baud = 9600            'UART2 baud rate
    Declare HRSOut2_Pin = PORTB.5           'Select which pin is to be used for TX with USART2
    PPS_Output(cOut_Pin_RP5, cOut_Fn_U2TX)  'Make Pin RB5 U1TX       


'Run this before the main program loop.
'Mainly to allow the display start up and configure.

'Delay to allow the AHT20 to start.
        DelayMS 40                         'AHT only requires 20ms but dont read for 40ms.
                                           

'Main Program Starts Here
Do
    DS3231_ReadDate()                                           ' Read the date from the DS3231
    HSerOut2 ["Date = ", DS3231_Get_DayName(RTC_DayOfWeek), " ",_  ' \
                      Dec2 RTC_Day, " ",_                        ' | Serially transmit the date as ASCII
                      DS3231_Get_MonthName(RTC_Month),_         ' |
                      " 20", Dec2 RTC_Year, 13]                   ' /

        DS3231_ReadTime()                                       ' Read the time from the DS3231
        HSerOut2 ["Time = ", Dec2 RTC_Hour, ":",_                   ' \
                          Dec2 RTC_Minute, ":",_                 ' | Serially transmit the time as ASCII
                          Dec2 RTC_Second, 13]                    ' /

        If AHT_CALL >= 2 Then           ' Only call the AHT20 sensor every 2 seconds
'Call the sensor read subroutine 
        GoSub AHT20
                 
        HSerOut2 ["Humidity ", Dec2 Humidity, " -- Temperature ", Dec2 Temperature, 13] 
        Clear AHT_CALL
        EndIf

        HSerOut2 [13]                   ' Create a space between readings

'Create a delay between reads, also show a time status on the display.   
   DelayMS 1000   
   Inc AHT_CALL             
Loop   

'--------------------------------------------------------------------------------

'Procedures
       
'Not currently used.
AHT_INIT:
'Trigger the measurement
        I2COut SDA, SCL, AHT_ADDR_WRITE, [AHT_CMD_TRIGGER,0x38,0x00]

'Wait for the measurement to complete       
        DelayMS 80

'Trigger the measurement
        I2COut SDA, SCL, AHT_ADDR_READ, [AHT_Data_0]
        Return

AHT20:   
'Trigger the measurement
        I2COut SDA, SCL, AHT_ADDR_WRITE, [AHT_CMD_TRIGGER,0x33,0x00]

'Wait for the measurement to complete       
        DelayMS 80
 'Read the raw data       
        I2CIn SDA, SCL, AHT_ADDR_READ, [AHT_Data_0, AHT_Data_1, AHT_Data_2,AHT_Data_3, AHT_Data_4, AHT_Data_5, AHT_Data_6]

'Do the humidity calculation       
        Clear Humidity_Temp
        Humidity_Temp_B2 = AHT_Data_1
        Humidity_Temp_B1 = AHT_Data_2
        Humidity_Temp_B0 = AHT_Data_3
        Humidity_Temp = Humidity_Temp >> 4
 
        Humidity = Humidity_Temp / 0x100000
        Humidity = Humidity * 100       

'Do the temperature calculation       
        Clear Temperature_Temp
        Temperature_Temp_B2 = AHT_Data_3 & 0x0F
        Temperature_Temp_B1 = AHT_Data_4 
        Temperature_Temp_B0 = AHT_Data_5 
         
        Temperature = Temperature_Temp / 0x100000   
        Temperature = Temperature * 200   
        Temperature = Temperature - 50
        Return

DS3231 include.
$ifndef _DS3231_INC_
$define _DS3231_INC_
'  ____/\\\\\\\\\_________/\\\\\\\\\\\\__/\\\________/\\\____/\\\\\\\\\_______/\\\\\\\\\\\\\\\______/\\\\\\\____       
'   __/\\\///////\\\_____/\\\//////////__\/\\\_______\/\\\__/\\\///////\\\____\/\\\///////////_____/\\\/////\\\__       
'    _\/\\\_____\/\\\____/\\\_____________\//\\\______/\\\__\///______\//\\\___\/\\\_______________/\\\____\//\\\_     
'     _\/\\\\\\\\\\\/____\/\\\____/\\\\\\\__\//\\\____/\\\_____________/\\\/____\/\\\\\\\\\\\\_____\/\\\_____\/\\\_     
'      _\/\\\//////\\\____\/\\\___\/////\\\___\//\\\__/\\\___________/\\\//______\////////////\\\___\/\\\_____\/\\\_   
'       _\/\\\____\//\\\___\/\\\_______\/\\\____\//\\\/\\\_________/\\\//____________________\//\\\__\/\\\_____\/\\\_   
'        _\/\\\_____\//\\\__\/\\\_______\/\\\_____\//\\\\\________/\\\/____________/\\\________\/\\\__\//\\\____/\\\__ 
'         _\/\\\______\//\\\_\//\\\\\\\\\\\\/_______\//\\\________/\\\\\\\\\\\\\\\_\//\\\\\\\\\\\\\/____\///\\\\\\\/___
'          _\///________\///___\////////////__________\///________\///////////////___\/////////////________\///////_____
'
' Procedures to access a DS3231 Real Time Clock/Calendar via a software I2C bus
' Modified from the DS1307 sample written by Les Johnson.
'
' Originally it used BusIn / BusOut but for some reason this did not work but it did when I use I2CIn / I2COut.
'
' Declare the default pins used for busin and busout
'
#ifnSym __SDA_Port
    Declare SDA_Pin = PORTB.0           ' SDA connected to this pin
#endIfSym
#ifnSym __SCL_Port
    Declare SCL_Pin = PORTB.1           ' SCL connected to this pin
#endIfSym
'
' Global Time variables
'
    Dim RTC_Second As Byte              ' Second (0..59)
    Dim RTC_Minute As Byte              ' Minute (0..59)
    Dim RTC_Hour   As Byte              ' Hour   (0..11 or 0..23)
'
' Global Date variables
'
    Dim RTC_Day       As Byte           ' Date  (0..31)
    Dim RTC_Month     As Byte           ' Month (1..12)
    Dim RTC_Year      As Byte           ' Year  (0..99)
    Dim RTC_DayOfWeek As Byte           ' Day of the week (1..7)
'
' DS3231 register addresses
'
     $define cRTC_DEV_ADDR  $D0         ' DS3231 device Address
     $define cRTC_TIME      $00         ' Address for time
     $define cRTC_WDAY      $03         ' Address for day of week number
     $define cRTC_DATE      $04         ' Address for date
     $define cRTC_CONTROL   $0E         ' Address for control byte
     $define cRTC_CTRL_STAT $0F         ' Address for control / Status byte
'
' Values - used in calls to DS3231_ReadControl() and DS3231_WriteControl()...
' Not used here, may need a bit more work.
     $define cRTC_SQWE       $10        ' Square Wave enable
     $define cRTC_A1IE       $01        ' Alarm 1 Interrupt Enable
     $define cRTC_A2IE       $02        ' Alarm 2 Interrupt Enable       
     $define cRTC_INTCN      $04        ' Interupt Control
     $define cRTC_SQWF_1Hz   $00        ' Square Wave frequency  1.0Hz     
     $define cRTC_SQWF_1KHz  $08        ' Square Wave frequency  1.024KHz
     $define cRTC_SQWF_4KHz  $10        ' Square Wave frequency  4.096KHz
     $define cRTC_SQWF_8KHz  $18        ' Square Wave frequency  8.192KHz
     $define cRTC_CONV       $20        ' Convert Temperature 
     $define cRTC_BBSQW      $40        ' Battery Backeed Square Wave Enable 
     $define cRTC_EOSC       $80        ' Enable oscillator

$ifndef False
    $define False 0
$endif
$ifndef True
    $define True 1
$endif
'----------------------------------------------------------------------------
' Convert a packed BCD (Binary Coded Decimal) value to a decimal value
' Input     : pValue holds the BCD value to convert to decimal
' Output    : Returns the decimal value
' Notes     : None
'
Proc DS3231_BCDToDec(pValue As Byte), Byte
    Result = (pValue >> 4) * 10
    Result = Result + (pValue & $0F)
EndProc

'----------------------------------------------------------------------------
' Convert a decimal value to packed BCD (Binary Coded Decimal) value
' Input     : pValue holds the decimal value to convert to BCD
' Output    : Returns the packed BCD value
' Notes     : None
'
Proc DS3231_DecToBCD(pValue As Byte), Byte
    Result = ((pValue / 10) << 4)
    Result = Result | (pValue // 10)
EndProc

'----------------------------------------------------------------------------
' Read a DS3231 register ($00..$12)
' Input     : pAddress holds the address of the register
' Output    : Returns the byte read from the register
' Notes     : None
'
Proc DS3231_ReadRegister(pAddress As Byte), Byte
    I2CIn SDA, SCL, cRTC_DEV_ADDR, pAddress,[Result]
EndProc

'----------------------------------------------------------------------------
' Write to a DS3231 register ($00..$12)
' Input     : pAddress holds the address of the register
'           : pData holds the byte to write to the register
' Output    : None
' Notes     : None
'
Proc DS3231_WriteRegister(pAddress As Byte, pData As Byte)
    I2COut SDA, SCL, cRTC_DEV_ADDR, pAddress,[Result]
EndProc

'----------------------------------------------------------------------------
' Read the RTC control byte ($0E)
' Input     : None
' Output    : Returns the byte read from the register
' Notes     : See the control constants cRTC_SQWXXXX above
'
Proc DS3231_ReadControl(), Byte
    Result = DS3231_ReadRegister(cRTC_CONTROL)
EndProc

'----------------------------------------------------------------------------
' Write the RTC Control byte ($0E)
' Input     : pData holds the byte to write to the register
' Output    : None
' Notes     : See the control constants cRTC_SQWXXXX above
'
Proc DS3231_WriteControl(pData As Byte)
    DS3231_WriteRegister(cRTC_CONTROL, pData)
EndProc

'----------------------------------------------------------------------------
' Read the Time
' Input     : None
' Output    : Global variable RTC_Second holds the seconds value (in decimal)
'           : Global Variable RTC_Minute holds the minutes value (in decimal)
'           : Global Variable RTC_Hour holds the hours value (in decimal)
' Notes     : None
'
Proc DS3231_ReadTime()
    I2CIn SDA, SCL, cRTC_DEV_ADDR, cRTC_TIME, [RTC_Second, RTC_Minute, RTC_Hour]

    RTC_Second = DS3231_BCDToDec(RTC_Second)       ' Convert the Seconds value to decimal
    RTC_Minute = DS3231_BCDToDec(RTC_Minute)       ' Convert the Minutes value to decimal
    RTC_Hour = DS3231_BCDToDec(RTC_Hour)           ' Convert the Hours value to decimal
EndProc

'----------------------------------------------------------------------------
' Read the Date
' Input     : None
' Output    : Global Variable RTC_DayOfWeek holds the week day value (in decimal)
'           : Global Variable RTC_Day holds the days value (in decimal)
'           : Global Variable RTC_Month holds the months value (in decimal)
'           : Global Variable RTC_Year holds the years value (in decimal)
' Notes     : None
'
Proc DS3231_ReadDate()
    I2CIn SDA, SCL, cRTC_DEV_ADDR, cRTC_WDAY, [RTC_DayOfWeek, RTC_Day, RTC_Month, RTC_Year]

    RTC_DayOfWeek = DS3231_BCDToDec(RTC_DayOfWeek)     ' Convert the WeekDay value to decimal
    RTC_Day = DS3231_BCDToDec(RTC_Day)                 ' Convert the Days value to decimal
    RTC_Month = DS3231_BCDToDec(RTC_Month)             ' Convert the Months value to decimal
    RTC_Year = DS3231_BCDToDec(RTC_Year)               ' Convert the Years value to decimal
EndProc

'----------------------------------------------------------------------------
' Set the Time
' Input     : pHour holds the hours value (in decimal)
'           : pMinute holds the minutes value (in decimal)
'           : pSecond holds the seconds value (in decimal)
' Output    : None
' Notes     : None
'
Proc DS3231_WriteTime(pHour As Byte, pMinute As Byte, pSecond As Byte)
    I2COut SDA, SCL, cRTC_DEV_ADDR, cRTC_TIME, [DS3231_DecToBCD(pSecond),_
                                      DS3231_DecToBCD(pMinute),_
                                      DS3231_DecToBCD(pHour)]                                 
EndProc

'----------------------------------------------------------------------------
' Set the Date
' Input     : pDayOfWeek holds the week day value (in decimal)
'           : pDay holds the days value (in decimal)
'           : pMonth holds the months value (in decimal)
'           : pYear holds the years value (in decimal)
' Output    : None
' Notes     : None
'
Proc DS3231_WriteDate(pDayOfWeek As Byte, pDay As Byte, pMonth As Byte, pYear As Byte)
    I2COut SDA, SCL, cRTC_DEV_ADDR, cRTC_WDAY, [DS3231_DecToBCD(pDayOfWeek),_
                                      DS3231_DecToBCD(pDay),_
                                      DS3231_DecToBCD(pMonth),_
                                      DS3231_DecToBCD(pYear)]                                 
EndProc

'----------------------------------------------------------------------------
' Return the name of the day
' Input     : pDayOfWeek holds the day value 1 to 7 (Sunday to Saturday)
' Output    : Returns a string holding the day's name
' Notes     : None
'
Proc DS3231_Get_DayName(pDayOfWeek As Byte), String * 9

    Select pDayOfWeek
        Case 1
            Result = "Sunday"
        Case 2
            Result = "Monday"
        Case 3
            Result = "Tuesday"
        Case 4
            Result = "Wednesday"
        Case 5
            Result = "Thursday"
        Case 6
            Result = "Friday"
        Case 7
            Result = "Saturday"
    EndSelect
EndProc

'----------------------------------------------------------------------------
' Return the name of the month
' Input     : pMonth holds the month value 1 to 12 (January to December)
' Output    : Returns a string holding the month's name
' Notes     : None
'
Proc DS3231_Get_MonthName(pMonth As Byte), String * 9

    Select pMonth
        Case 1
            Result = "January"
        Case 2
            Result = "February"
        Case 3
            Result = "March"
        Case 4
            Result = "April"
        Case 5
            Result = "May"
        Case 6
            Result = "June"
        Case 7
            Result = "July"
        Case 8
            Result = "August"
        Case 9
            Result = "September"
        Case 10
            Result = "October"
        Case 11
            Result = "November"
        Case 12
            Result = "December"
    EndSelect
EndProc

'----------------------------------------------------------------------------
' Detect the DS3231
' Input     : None
' Output    : Returns 1 if the DS3231 is available
' Notes     : Uses the Ack return for confirmation
'           : This procedure assumes that there is only 1 I2C device attached to the bus
'
Proc DS3231_Present(), Bit
     BusIn cRTC_DEV_ADDR, cRTC_TIME,[WREG0]     ' Attempt to read from the DS3231 chip
     Result = ~SRbits_C                         ' Invert the Ack return
EndProc

'----------------------------------------------------------------------------

$endif  ' _DS3231_INC_