DRF1276DM with HTU21D-F breakout board

johnlong

Senior Member
Hi All
Have being having a play around with the drf1276dm and the adafruit htu21d-f breakout board to create a remote connection
between 2- 28x2
The code for the htu21d is a rework of Phil Hornsbys htu21d demo.bas on the remote unit.
The only problem I encounted with the drf1276dm was with the DRF tool not recongising the presense of the unit when using the dac02 driver
This was over come by using jumper wires (male-female) connecting the 2 units from 1 to 5 omitting 6 and 7. Other than that its quite an impresive and simple to use piece of kit
Master Code
Code:
'Connection for the DRF1276DM to the picaxe 28X2
'picaxe A.1(TXD)--------Pin 4 (RXD) DRF
'picaxe A.2(RXD)--------Pin 5 (TXD) DRF
'used to wake up Picaxe up from sleep mode

#picaxe 28x2
#no_data
#no_table

 Symbol Qualifier= 254 
symbol fail=b25
symbol lamp=w7
symbol dry=w8
symbol rh=w9
symbol linked=b8
symbol fr=b10
pause 2000
      MAIN:
      do
    sertxd("MAIN",cr,lf)
  low b.7
   serout A.1,T9600,(85,85,85,85,Qualifier,"Hello")'wake up slave call
      serin A.2,T9600,(Qualifier,"ACK")' slave connected responce
      serin[2000], A.2,T9600,linked
     if linked="X" then 'X indicates running slot 1 on slave to initalise HTU21D on first up power
        linked=0
        pause 1000
        goto lingalong
        endif

    

obtain:
    
       b5=0'call to measure light levels
        
    serout A.1,T9600,(b5)'tell remote unit which reading to undertake
    do
     serin A.2,T9600,lamp 'result from remote unit
     
     serout A.1,T9600,(lamp) 'bounce result back to check for errors
     
     serin A.2,T9600,b0 'master waits until conformation of value or error from slave
     loop until b0="Y" or b0="N"
     if b0="N" then
        sertxd("light sensor error",cr,lf)
endif   
    
    'sertxd("lamp ",#lamp," b0 ",#b0," b5 ",#b5,cr,lf)
    'call to test supply state prior to read
    do
    b5=1
    serout A.1,T9600,(b5):pause 20 'want case
    serin A.2,T9600,b0,b1 'yes or no answer no value
    loop until b0="Y" or b0="N"
    if b0="N" then
        sertxd(" sensor error",cr,lf)
        'pause 2000
        'goto main
endif    
    'sertxd("1st Supply b0 ",#b0," b1 ",#b1,cr,lf)
    do
    b5=2
    serout A.1,T9600,(b5):pause 20
    serin A.2,T9600,b0,b1 'yes or no answer no value
    loop until b0="Y" or b0="N"
        
     if b0="N" then
        sertxd("Battery Low Change",cr,lf)
        'pause 2000
        'goto main
    endif
    'sertxd("2nd Supply b0 ",#b0," b1 ",#b1,cr,lf)
     
     b5=3'call to measure tempreture
    serout A.1,T9600,(b5)'tell remote which reading to undertake
    do
     serin A.2,T9600,dry
     serout A.1,T9600,(dry)
     serin A.2,T9600,b0,b1
     loop until b0="Y" or b0="N"
     if b0="N" then
        sertxd("tempreture sensor error",cr,lf)
    endif 
    'sertxd("dry ",#dry," b0 ",#b0," b1 ",#b1," b5 ",#b5,cr,lf)
     
     b5=4'call to measure humidity
    serout A.1,T9600,(b5)'tell remote which reading to undertake
    do
     serin A.2,T9600,rh
     serout A.1,T9600,(rh)
     serin A.2,T9600,b0,b1
     loop until b0="Y" or b0="N"
     if b0="N" then
        sertxd("humidity sensor error",cr,lf)
    endif 
    'sertxd("rh ",#rh," b0 ",#b0," b1 ",#b1," b5 ",#b5,cr,lf)
     b5=5'call to measure light levels
        
    serout A.1,T9600,(b5)'tell remote unit which reading to undertake
    do
     serin A.2,T9600,fr 'result from remote unit
     
     serout A.1,T9600,(fr) 'bounce result back to check for errors
     
     serin A.2,T9600,b0 'master waits until conformation of value or error from slave
     loop until b0="Y" or b0="N"
     if b0="N" then
        sertxd("light sensor error",cr,lf)
endif   
      b5="z"
    serout A.1,T9600,(b5)'w5 end loop in slave return to main
    sertxd("lamp ",#lamp," Dry ",#dry," Hum ",#rh," FR ",#fr,cr,lf)
    
    lingalong:
    high B.7
    sertxd("in timing loop",cr,lf)
    for b10= 1 to 30
     pause 1000
next b10
    sertxd("out of timing loop",cr,lf)
sertxd(cr,lf)
       loop
    
none: 'for future development
    serout B.1,N9600,("sensor unit failed to read")
    b0="z"
    return
slave to follow
 

johnlong

Senior Member
Slave code Slot 1 initalising htu21d
Code:
  '#rem
#slot 1
#no_data
#no_table

#picaxe 28x2
#no_data
#no_table

;Writen by Phillip J Hornby HTU21D_demo.bas 22/02/17 code comments by P Hornsby

; I2C registers
;
symbol sspmsk = $6F
symbol sspcon2 = $C5
symbol sspcon1 = $C6
symbol sspstat = $C7
symbol sspadd = $C8
symbol sspbuf = $C9
;
; SSPCON2 bits
;
symbol SEN = 0
symbol PEN = 2
symbol ACKSTAT = 6

symbol TemperatureRAW     = W23
symbol Temperature     = W24
symbol Humidity         = b50

symbol rxCRC         = b51
symbol HTU21Data         = W26
 symbol LSB         =  b52
 symbol MSB         =  b53
symbol CRC             = b54
symbol DATABYTE         = b55
symbol error =b18
symbol themode=b20
Symbol Qualifier= 254
symbol HTU21DAddress = %10000000        ;I2C address of HTU21D is 0x40 - shift it left one bit

symbol TemperatureHOLD = $E3        ;read temperature - HTU21D uses clock-stretching to make it 
                        ;a synchronous operation
symbol HumidityHOLD = $E5                    ;ditto - humidity
symbol TemperatureNOHOLD = $F3                ;asynchronous
symbol HumidityNOHOLD = $F5                    ;ditto - humidity
symbol WriteUser = $E6                        ;write to User register
symbol ReadUser = $E7                        ;read user register
symbol SoftReset = $FE                        ;reboot HTU21D

symbol Heater = 2                            ;on-chip heater
symbol SupplyOK = 6                        ;bit within the User Register that describes PSU  condition

symbol POLY = 0x31                        ;Used in CRC generation => X^8 + X^5 + X^4 + 1  

    #macro ComputeCRC(val1,val2)
        CRC = 0                        ;crc_t crc_init - in original 'C' code
        DATABYTE = val1 : gosub crc_update        ;msb
        DATABYTE = val2 : gosub crc_update        ;lsb
    #endm    

    #macro ComputeCRC1(val)
        CRC = 0                        ;crc_t crc_init - in original 'C' code
        DATABYTE = val : gosub crc_update        ;msb
    #endm    

    



    hi2csetup i2cmaster,HTU21DAddress,i2cfast,i2cbyte ; setup i2c parameters
    serout B.0,T9600,(Qualifier,"ACK")'1
    pause 200
    error="X"
    serout B.0,T9600,(error)
    hintflag=0:hint2flag=0
    high b.6
    low b.
    gosub Get_SupplyState                    ;check existence of device and supply 
;Serial no. stuff - relies on CRC for error checking.
;
    hi2cout (%11111010,%00001111)        ;0xFA,0x0F - Get SNB_0, SNB_1, SNB_2 & SNB_3
    hi2cin (b0,b1,b2,b3,b4,b5,b6,b7) 'Check fixed bytes - and fixed CRC's
;
    if W0 <> $0000 then                    ;SNB_3: Expect b0 = 0 and b1 (its crc) = 0
        error=1
        gosub CRCerr
    endif
;
; Check actual CRC on other bytes
;
    ComputeCRC1(b2)                        ;SNB_2: b2 is 1st part of variable serial no.
    if b3 <> CRC then                        ;b3 is the expected CRC
        error=1
        gosub CRCerr
    endif

    ComputeCRC1(b4)                        ;SNB_1: b4 is 2nd part of variable serial no.
    if b5 <> CRC then                        ;b5 is the expected CRC
        error=1
        gosub CRCerr
    endif

    ComputeCRC1(b6)                        ;SNB_0: b6 is 3rd part of variable serial no.
    if b7 <> CRC then                        ;b7 is the expected CRC
        error=1
        gosub CRCerr
    endif
;    
;Request Part deux (rest of Serial no. is in a different location)
;
    hi2cout (%11111100,%11001001)                ;0xFC,0xC9 - Get SNC_1 and SNC_0
    hi2cin (b0,b1,b3,b8,b9,b10) ; More CRCs - but in different format
;
    ComputeCRC(b0,b1)                ;SNC_1 (0x32), SNC_0: b1 is 4th part of Serial No.
    if b3 <> CRC then                        ;b3 is the expected CRC
        error=2
        gosub CRCerr
    endif

    if W4 <> $5448 or b10 <> $04 then        ;These are fixed, so no need to calculate CRC
        error=2
        gosub CRCerr
    endif

    b3 = b1                            ;save b1 (used by b0_to_hex routine)
    
        ;first part is fixed (but we checked anyway)
    b0 = b2 : gosub b0_to_HEX                ;SNB_2
    b0 = b4 : gosub b0_to_HEX                ;SNB_1
    b0 = b6 : gosub b0_to_HEX                ;SNB_0
                            ;another fixed section
    b0 = b3 : gosub b0_to_HEX                ;SNC_0

    sertxd (cr,lf,cr,lf)
    gosub TurnOnHeater
    themode=1
    run 0
CRCerr:
    
    if error =1 then
        hi2cout (%11111010,%00001111)                ;0xFA,0x0F - Get SNB_0, SNB_1, SNB_2
    hi2cin (b0,b1,b2,b3,b4,b5,b6,b7)
    error=0
    elseif error=2 then
        hi2cout (%11111100,%11001001)                ;0xFC,0xC9 - Get SNC_1 and SNC_0
    hi2cin (b0,b1,b3,b8,b9,b10)
    error=0
endif
return
    
TurnOnHeater:
    
    heat:
    hi2cin ReadUser,(b0);Send ReadUser, read user register back (NO CRC).
    setbit b0,Heater    ; turn on the heater
    hi2cout WriteUser,(b0)                    ;and send to device
    Pause 10000                            ;wait for it.
    hi2cout (SoftReset)                    ;HTU21D reboot/reset to defaults
    pause 15
    peeksfr sspcon2,b0                    
    
      if b0 bit ACKSTAT set then    ;bit 6 is ackstat and should be zero, if ACK present
        hi2cout (SoftReset)
      pause 15
    endif 
      return

Get_SupplyState:
    
    supply:
    hi2cin ReadUser,(b0)                    ;Send ReadUser, read user register back 
    peeksfr sspcon2,b1           
    
      if b1 bit ACKSTAT set then    ;bit 6 is ackstat and should be zero, if ACK present
       hi2cout (SoftReset)
      pause 15
    endif 
    
    state:
    if b0 bit SupplyOK set then
         hi2cout (SoftReset)
      pause 15        
endif 
    return
crc_update:
    pushram                            ;20x2 extravagance! comments from P Hornsbys code using 28x2
    b1 = %10000000            ;make a mask, to examine the incoming byte, bit by bit...
    for b2 = 7 to 0 step -1                    ;...working from Right to left.
    bit0 = CRC AND %10000000 / %10000000     ;get the current state of bit7 of the CRC - a
        b3 = DATABYTE AND b1                ;is the bit being examined via our mask
        if b3 <> 0 then                    ;YES
            bit0 = NOT bit0                ;complement the bit obtained from CRC bit7
        endif
        CRC = CRC * 2                    ;shift CRC one place left
        if bit0 = 1 then
            CRC = CRC XOR POLY
        endif
        b1 = b1 / 2                        
    next b2
    popram
    return        

B0_TO_HEX:'convert hex to ascii
    b1 = b0 / 16 + "0"
    gosub Nybble
    b1 = b0 & 15 + "0"
Nybble:
    if b1 > "9" then : b1 = b1 + 7    endif
    sertxd(b1)
    return
    #endrem
 

johnlong

Senior Member
Slave code data reading between the units
Code:
 ;Adaptied from Phillip J Hornby HTU21D_demo.bas 22/02/17 code comments by P Hornsby unless **
  'Connection for the DRF1276DM to the picaxe 28X2
'picaxe B.0(TXD)--------Pin 4 (RXD) DRF
'picaxe B.1(RXD)--------Pin 5 (TXD) DRF
'picaxe B.2--------Pin 6 (AUX) DRF indication of data in/out 2ms in advance of send/recieve
'used to wake up Picaxe up from sleep mode        UNIT SETTINGS FOR drf1276dm
                '28x2                 power level 6 RF-freq 433.9 RF_bw 125 RF_Factor 2048 baud 9600
    '            ---------------
      'photo resistor    | A.0        B.2  | AUX  to Pin 6 (AUX) DRF
    '            |            B.1  | RXD  to Pin 5 (TXD) DRF
    '            |            B.0  | TXD  to Pin 4 (RXD) DRF
    ''            |            C.4  | SDA to HTU21D-F Adafruit breakout board 3v to 5v using 5v
    '    DS18B20    |C.2         C.3  | SCL to HTU21-F

     
     '#rem
#no_data
#no_table
#slot 0

symbol TD7 = b7 symbol TD6=b6 symbol TD5=b5 symbol TD4=b4 symbol TD3=b3 symbol TD2=b2 symbol TD1=b1 symbol TD0=b0
symbol error=b45
symbol themode=b20
'**************************
symbol result=w23 'b46,b47
symbol RH=b50
 Symbol Qualifier= 254 'used for wireless communications 
symbol fail=b25
symbol want=b26
symbol lamp=w7
symbol Dry     = W24 ;b48,b49
symbol rxCRC         = b51
symbol HTU21Data         = W26 'b53,b52
 symbol LSB         =  b52
 symbol MSB         =  b53
symbol CRC             = b54
symbol DATABYTE         = b55
symbol HTU21DAddress = %10000000:symbol TemperatureHOLD=$E3:symbol HumidityHOLD = $E5:symbol TemperatureNOHOLD = $F3
symbol HumidityNOHOLD = $F5:symbol WriteUser = $E6:symbol ReadUser = $E7:symbol SoftReset = $FE                
symbol Heater = 2:symbol SupplyOK = 6:symbol POLY = 0x31;Used in CRC generation => X^8 + X^5 + X^4 + 1
; I2C registers                
symbol sspmsk = $6F:symbol sspcon2 = $C5:symbol sspcon1 = $C6:symbol sspstat = $C7:symbol sspadd = $C8
symbol sspbuf = $C9
; SSPCON2 bits
symbol SEN = 0:symbol PEN = 2:symbol ACKSTAT = 6
symbol HTU21D_0= 17474:symbol HTU21D_Minus40= 2555:symbol HTU21D_4685= 34948:symbol HTU21D_80= 47310:symbol HTU21D_125= 64092
;Closest value to 0 (0.0026);Closest value to -40 (-39.999);Closest value to 46.85 (46.855);closest value to 80 (80.001)
;Closest value to 125 (124.998)
    
    #macro ComputeCRC(val1,val2)
        CRC = 0                        ;crc_t crc_init - in original 'C' code
        DATABYTE = val1 : gosub crc_update        ;msb
        DATABYTE = val2 : gosub crc_update        ;lsb
    #endm    

    #macro ComputeCRC1(val)
        CRC = 0                        ;crc_t crc_init - in original 'C' code
        DATABYTE = val : gosub crc_update        ;msb
    #endm
    #MACRO Talk_Talk(var,var1)
    if var=var1 then:fail=0:serout B.0,T9600,("Y",td7):endif
    if var<>var1:then:if fail=2 then:serout B.0,T9600,("N",td7):fail=0:endif:endif
    #endm
    #macro bit_supply(var)
    if var=0 then:serout B.0,T9600,("Y",TD7):error=0:endif
    if var=1 then:hi2cout (SoftReset):pause 15:endif
    if var=2 then:serout B.0,T9600,("N",TD7):error=0:endif
    #endm
    
    hi2csetup i2cmaster,HTU21DAddress,i2cfast,i2cbyte
    hintsetup %00000100
    pause 1000
'*******************************************************************************
main:  
        
    do
    low B.7    
       enablebod 'low power
     sleep 0 'woken up via pin B.2 attached to AUX on DRF sets hint and hint2 flags
     disablebod 'power up
    Serin B.1, T9600,(Qualifier,"Hello") 'call from master DRF unit
    if themode=0 then:run 1:endif
    if hint2flag=1 then
            hintflag=0:hint2flag=0
        high B.7 
        want=0
        pause 500
        serout B.0,T9600,(Qualifier,"ACK")
        gosub obtain
        endif
    loop
obtain:
    do
    serin B.1,T9600,want
    if want="z" then
        exit 
        endif
            on want gosub c0,c1,c2,c3,c4,c5
        loop
        return
    c0: 'read light
    readadc A.0,w5 
    
     do
     serout B.0,T9600,(w5)
     pause 20
      serin B.1,T9600,w6
      if w5<>w6 then
          fail=fail+1
    endif
      Talk_Talk(w5,w6)  'macro controlls readings loops sends release to master for next read **
      
    loop until fail=0
      return
c1: 'supply read
    do
    hi2cin ReadUser,(b0)                ;Send ReadUser, read user register back (NO CRC).
    
    peeksfr sspcon2,b1      ;bit 6 is ackstat and should be zero, if ACK present $C5 197
    
      if b1 bit ACKSTAT set then
        error=2
            TD7="E"
    endif 
    bit_supply(error)'serout in macro
    td7=0
    loop until error=0 
    
    return    
 c2:
    do 
        
    if b0 bit SupplyOK set then 'bit2
        error=2
             TD7="E"
    endif
    bit_supply(error)
    td7=0
    loop until error=0 
    return
 
    c3: 'temp degC
    tempread:
    hi2cin TemperatureHOLD,(MSB,LSB,rxCRC)        ;temperature measurement next case
                                    ;rely on CRC to detect any comms error
    ComputeCRC(MSB,LSB)'gosub crc update
    if rxCRC <> CRC then
    td7="E"    
    endif
    
    result = HTU21Data & $FFFC            ;zero bottom 2 bits
    if result < HTU21D_0 then            ;-ve?
    W1 = HTU21D_4685 - result min HTU21D_Minus40    ;and constrain min to -40.0
    else                                ;otherwise positive...
        W1 = result max HTU21D_125        ;...constrain max to +125.0
    endif
    dry = 17572 ** W1 - 4685            ;Basic calculation
    dry = dry + 5 / 10
    
    bintoascii Dry,TD0,TD1,TD2,TD3,TD4    ;Temperature = 10 x Temp (i.e. 1dp)    
    dry= TD2-48*10 '** round up to whole values
    TD3=TD3-48
    TD4=TD4-48    
    if TD4>=5 then
    TD3=TD3+1
    endif     
    dry=dry+TD3
    w5=dry
    do
    serout B.0,T9600,(w5)
     pause 20
      serin B.1,T9600,w6
      if w5<>w6 then
          fail=fail+1
        endif   
      Talk_Talk(w5,w6)   'macro controlls readings loops sends release to master for next read **
      td7=0
      loop until fail=0
      
        return
'************************************************************
c4: 'Hum %rh first action turn on the heater
     humheat:
    
    hi2cin ReadUser,(b0)    ;Send ReadUser, read user register back (NO CRC).
    setbit b0,Heater        ;turn on the heater
    hi2cout WriteUser,(b0)                    ;and send to device
    pause 5000
    hi2cout (SoftReset) ;HTU21D reboot/reset to defaults
    pause 15
    peeksfr sspcon2,b0   ;bit 6 is ackstat and should be zero, if ACK present 197
      if b0 bit ACKSTAT set then
        error=2
        td7="B"
    endif
    
     humread:
    hi2cin HumidityHOLD,(MSB,LSB,rxCRC)            ;humidity measurement
    ComputeCRC(MSB,LSB)
    if rxCRC <> CRC then
        error=2
        td7="C"
    endif
    
    W0 = HTU21Data & $FFFC                    ;zero bottom 2 bits
    RH = 125 ** W0 MIN 6 - 6 max 100        ;Constrain RH to 0~100%
    if result >= HTU21D_0 and result =< HTU21D_80 then ; only applies between 0 and 80.0

        W0 = 250 - dry                    ;part 1 of calculation (25-Tempactual)
        if W0 >= $8000 then                    ;sign bit set.
            W0 = - W0 * 15                    ;Negative - make it positive (neg * n
            if W0 >= 1000 then
                W1 = W0 / 1000                ;Get no. of whole %age points
                RH = RH + W1 max 100    ;and apply (constrain to 100%)
                W1 = W1 * 1000                ;get...
                W0 = W0 - W1                ;...remainder    
            endif
            if W0 >= 500 then                    ;500 = 0.5 percent
                RH = RH + 1 max 100    ;correct and constrain to 100%
            endif
        else
        
        W0 = W0 * 15
        
            if W0 >= 1000 then
                W1 = W0 / 1000
                if RH > W1 then            ;Don't end up up with RH < 0%
                    RH = RH - W1    ;Correct it...
                else
                    RH = 0            ;...or set to min.
                endif
                W1 = W1 * 1000
                W0 = W0 - W1
            endif
            
            if W0 >= 500 then                    ;500 = 0.5 percent
                if RH >= 1 then            ;Don't end up up with RH < 0%
                    RH = RH - 1        ;otherwise, correct it.
                endif
            endif
        endif
        endif 
        
        w5=RH
        do
        serout B.0,T9600,(w5)
     pause 20
      serin B.1,T9600,w6
      if w5<>w6 then
          fail=fail+1
    endif 
     Talk_Talk(w5,w6)   'macro
     td7=0
     loop until fail=0
     
return
c5:     readtemp C.2,w5
         do
     serout B.0,T9600,(w5)
     pause 20
      serin B.1,T9600,w6
      if w5<>w6 then
          fail=fail+1
    endif
      Talk_Talk(w5,w6)  'macro controlls readings loops sends release to master for next read
      
    loop until fail=0
      return
      '******************************subs
    
    
    
    crc_update:
    pushram                            ;20x2 extravagance!
    b1 = %10000000            ;make a mask, to examine the incoming byte, bit by bit...
    for b2 = 7 to 0 step -1                    ;...working from Right to left.
    bit0 = CRC AND %10000000 / %10000000     ;get the current state of bit7 of the CRC 
    b3 = DATABYTE AND b1        ;is the bit being examined via our mask, SET in the data byte
        if b3 <> 0 then                    ;YES
            bit0 = NOT bit0                ;complement the bit obtained from CRC bit7
        endif
        CRC = CRC * 2                    ;shift CRC one place left
        if bit0 = 1 then
    CRC = CRC XOR POLY    ; probably deeply significant ;-) (XOR = Division without carry)
        endif
        b1 = b1 / 2                    ;Shift mask right to point at next bit of data
    next b2
    popram
    return
    '#endrem
regards john
 
Top