' ============================================================================== ' ' File...... SHT11.BS2 ' Purpose... Control peltier cooler via SHT11, AD592 and IRL3103 ' Author.... Joel Gonzalez ' E-mail.... joel.gonzalez@backyardastronomy.net ' Date...... 07/07/11 ' Version... v1.01 ' - Added LCD Display ' ' {$STAMP BS2e} ' {$PBASIC 2.5} ' ' ============================================================================== ' ------------------------------------------------------------------------------ ' Program Description ' ------------------------------------------------------------------------------ ' ------------------------------------------------------------------------------ ' I/O Definitions ' ------------------------------------------------------------------------------ Buzzer CON 0 ' Buzzer pin rcPin CON 5 ' RCTIME pin Switch CON 12 ' FET switch pin LCD CON 13 ' LCD display pin Clock CON 14 ShtData CON 15 ' bi-directional data ping ' ------------------------------------------------------------------------------ ' Constants ' ------------------------------------------------------------------------------ ShtTemp CON %00011 ' read temperature ShtHumi CON %00101 ' read humidity ShtStatW CON %00110 ' status register write ShtStatR CON %00111 ' status register read ShtReset CON %11110 ' soft reset (wait 11 ms after) Ack CON 0 NoAck CON 1 No CON 0 Yes CON 1 MoveTo CON 2 ' for DEBUG control ClrRt CON 11 ' clear DEBUG line to right DegSym CON 186 ' degrees symbol for DEBUG LcdBaud CON 396 ' 9600 baud rate for LCD display Baud CON 84 ' Serin baudrate LcdBkSpc CON $08 ' move cursor left LcdRt CON $09 ' move cursor right LcdLF CON $0A ' move cursor down 1 line LcdCls CON $0C ' clear LCD (use PAUSE 5 after) LcdCR CON $0D ' move pos 0 of next line LcdOff CON $15 ' LCD off LcdOn1 CON $16 ' LCD on; cursor off, blink off LcdOn2 CON $17 ' LCD on; cursor off, blink on LcdOn3 CON $18 ' LCD on; cursor on, blink off LcdOn4 CON $19 ' LCD on; cursor on, blink on LcdLine1 CON $80 ' move to line 1, column 0 LcdLine2 CON $94 ' move to line 2, column 0 ' ------------------------------------------------------------------------------ ' Variables ' ------------------------------------------------------------------------------ 'SHT11 variables ioByte VAR Byte ' data from/to SHT1x ackBit VAR Bit ' ack/nak from/to SHT1x toDelay VAR Byte ' timeout delay timer timeOut VAR Bit ' timeout status soT VAR Word ' temp counts from SHT1x tC VAR Word ' temp - celcius soRH VAR soT ' humidity counts from SHT1x rhLin VAR Word ' humidity; linearized rhTrue VAR rhLin ' humidity; temp compensated status VAR Byte ' SHT1x status byte 'dewpoint calc variables degC VAR tC ' degrees Celsius (* 10 for dewpoint calculation) RH VAR rhLin ' % relative humidity (* 10 ditto) logEW VAR soT ' log base 10 of saturation water vapor pressure at degC DP VAR Word ' dew point degrees Celsius ix VAR Nib ' index for loops wx VAR Word ' temporary variable wy VAR Word ' temporary variable wz VAR Word ' temporary variable wj VAR Word ' temporary variable for integer part sign VAR Bit ' sign for calculations bt VAR Bit ' bit variable for calculations 'AD592 variables Kal VAR soT ' for calibration constant TK VAR tC ' Kelvin temperature. rct VAR rhLin ' Reading from RCTIME. adTc VAR ioByte ' AD592 Degrees Celsius. calInput VAR toDelay ' User input variable. userInput VAR Nib ' Variable for SERIN offset VAR Word ' Temp offset cooler VAR Bit ' Cooler "On" or "Off" ' ------------------------------------------------------------------------------ ' EEPROM Data ' ------------------------------------------------------------------------------ EKal DATA Word 15300 ' Constant to be determined. ' ------------------------------------------------------------------------------ ' LCD Custom Characters ' ------------------------------------------------------------------------------ SEROUT LCD, LcdBaud, [250, %01000, ' Temp degree sign %10100, %01000, %00000, %00000, %00000, %00000, %00000] SEROUT LCD, LcdBaud, [251, %00100, ' Up arrow for cooler ON %01010, %10101, %00100, %00100, %00100, %00100, %00000] SEROUT LCD, LcdBaud, [252, %00100, ' Down arrow for cooler OFF %00100, %00100, %00100, %00100, %10101, %01010, %00100] ' ------------------------------------------------------------------------------ ' Initialization ' ------------------------------------------------------------------------------ offset = 0 ' Set temp offset to 0 LOW Switch ' Start with cooler "OFF" FREQOUT Buzzer, 100, 3000, 4000 ' Start bip PAUSE 100 FREQOUT Buzzer, 100, 3000, 4000 ' Start bip SEROUT LCD, LcdBaud, [LcdOn1, LcdCls] ' Turn on LCD display and clear it PAUSE 5 SEROUT LCD, LcdBaud, [128, "Peltier Cooler", 148, "Controller v1.01"] PAUSE 2000 Initialize: GOSUB SHT_Connection_Reset ' reset SHT11 connection ' ------------------------------------------------------------------------------ ' Program Code ' ------------------------------------------------------------------------------ Main: DEBUG CLS DEBUG "BS2 Controlled Peltier Cooler", CR DEBUG "Press 1 to calibrate AD592", CR DEBUG "Press 2 to change offset value", CR DEBUG "-------------------------------", CR Main2: DEBUG MoveTo, 0, 5 DEBUG "Cooler (ON=1 Off=0): ", DEC1 cooler, CR IF (cooler = 1) THEN SEROUT LCD, LcdBaud, [135, 3] ELSE SEROUT LCD, LcdBaud, [135, 4] ENDIF GOSUB SHT_Measure_Temp DEBUG MoveTo, 0, 7 DEBUG "tC....... " DEBUG DEC (tC / 10), ".", DEC1 tC, DegSym, ClrRt, CR SEROUT LCD, LcdBaud, [128, "C=", DEC (tC / 10), ".", DEC1 tC, 2] GOSUB SHT_Measure_Humidity DEBUG MoveTo, 0, 8 DEBUG "rhTrue... " DEBUG DEC (rhTrue / 10), ".", DEC1 rhTrue, "%", ClrRt SEROUT LCD, LcdBaud, [136, "rh=", DEC (rhTrue / 10), ".", DEC1 rhTrue, "%"] GOSUB getDewPoint DEBUG MoveTo, 0, 9 DEBUG "dpC...... ",REP "-"\sign,DEC ABS DP/10,".",DEC1 ABS DP, DegSym, CR SEROUT LCD, LcdBaud, [148, "dp=", REP "-"\sign,DEC ABS DP/10,".",DEC1 ABS DP, 2] GOSUB AD592 DEBUG MoveTo, 0, 10 DEBUG "ad592C... ", DEC adTc, DegSym, CR SEROUT LCD, LcdBaud, [156, " pC=", DEC adTc, 2] DEBUG "Offset... ", SDEC offset, DegSym, CR 'DEBUG "adTc... ", SDEC adTc, CR GOSUB IRL3103 SERIN 16, Baud, 1000, Main2, [DEC1 userInput] ' Wait 1 sec for user input IF (userInput = 1) THEN GOSUB Calibrate ' If user enters "1" go to Calibrate sub ELSEIF (userInput = 2) THEN GOSUB tempOffset ' If user enters "2" go to Offset sub ENDIF GOTO Main END ' ------------------------------------------------------------------------------ ' Sht11 Subroutines ' ------------------------------------------------------------------------------ ' connection reset: 9 clock cyles with ShtData high, then start sequence ' SHT_Connection_Reset: SHIFTOUT ShtData, Clock, LSBFIRST, [$FFF\9] ' generates SHT1x "start" sequence ' _____ _____ ' ShtData |_______| ' ___ ___ ' Clock ___| |___| |___ ' SHT_Start: INPUT ShtData ' let pull-up take line high LOW Clock HIGH Clock LOW ShtData LOW Clock HIGH Clock INPUT ShtData LOW Clock RETURN ' measure temperature ' -- celcius = soT * 0.01 - 40 ' -- fahrenheit = soT * 0.018 - 40 ' SHT_Measure_Temp: GOSUB SHT_Start ' alert device ioByte = ShtTemp ' temperature command GOSUB SHT_Write_Byte ' send command GOSUB SHT_Wait ' wait until measurement done ackBit = Ack ' another read follows GOSUB SHT_Read_Byte ' get MSB soT.HIGHBYTE = ioByte ackBit = NoAck ' last read GOSUB SHT_Read_Byte ' get LSB soT.LOWBYTE = ioByte ' Note: Conversion factors are multiplied by 10 to return the ' temperature values in tenths of degrees tC = soT / 10 - 400 ' convert to tenths C 'tF = soT ** 11796 - 400 ' convert to tenths F RETURN ' measure humidity ' SHT_Measure_Humidity: GOSUB SHT_Start ' alert device ioByte = ShtHumi ' humidity command GOSUB SHT_Write_Byte ' send command GOSUB SHT_Wait ' wait until measurement done ackBit = Ack ' another read follows GOSUB SHT_Read_Byte ' get MSB soRH.HIGHBYTE = ioByte ackBit = NoAck ' last read GOSUB SHT_Read_Byte ' get LSB soRH.LOWBYTE = ioByte ' linearize humidity ' rhLin = (soRH * 0.0405) - (soRH^2 * 0.0000028) - 4 ' ' for the BASIC Stamp: ' rhLin = (soRH * 0.0405) - (soRH * 0.004 * soRH * 0.0007) - 4 ' ' Conversion factors are multiplied by 10 and then rounded to ' return tenths ' rhLin = (soRH ** 26542) rhLin = rhLin - ((soRH ** 3468) * (soRH ** 3468) + 50 / 100) rhLin = rhLin - 40 ' temperature compensated humidity ' rhTrue = (tC - 25) * (soRH * 0.00008 + 0.01) + rhLin ' ' Conversion factors are multiplied by 100 to improve accuracy and then ' rounded off. ' rhTrue = ((tC / 10 - 25) * (soRH ** 524 + 1) + (rhLin * 10)) + 5 / 10 RETURN getDewPoint: ' enter with -400 wj + (wz/65536) wx=-sign^(wj*10000+(wz**10000))+sign ' convert to decimal x.xxxx * 10000 & extend sign logEW=wx+logEW wx=RH GOSUB log2 ' find (log base 2 of wx) => wj + (wz/32768) wx=(wj*4000**49321)+(wz**6021) ' convert base 10, x.xxxx * 10000 logEW=wx+logEW-30000 ' -30000, because RH is 0->1000 ' range of logEW: ' maximum at +100 degrees C, 100%RH, where logEW=+28843 (+2.8843) ' minimum at -40 degrees C, 1%RH, where logEW=-28598 (-2.8598) ' calculate logEW/4 (so divisor in divide below will be <32768) sign=logEW.BIT15 logEW=-sign^(ABS logEW+2/4)+sign ' logEW/4, sign extended wx=1652-logEW ' dividend (from Magnus, 6608/4=>1552) sign=~wx.BIT15 ' for dewpoint calculation, DP sign is opposite of wx wx=ABS wx wy=20402-logEW ' divisor (from Magnus, 81608/4=>20402 GOSUB divide ' this a always a proper fraction, no integer part DP=23730**wz+5/10 ' fractional multiply, note extra decimal place and roundoff DP=-sign^DP+sign ' extend sign RETURN divide: ' enter with wx and wy positive integers to divide wj=wx/wy ' integer part of result FOR ix=15 TO 0 wx=wx//wy<<1 wz.BIT0(ix)=wx/wy NEXT RETURN ' wz to be fractional part (as wz/65536 implied) log2: ' enter with wx, to find log base 2 wj=NCD wx - 1 ' integer part of result (characteristic, 0<=wb<=15) wx=wx<<(15-wj) ' left justify the operand wz=0 FOR ix=14 TO 0 wy=wx**wx wz.BIT0(ix)=wy.BIT15 bt=~wy.BIT15 wx=wy<