;Remote sensing and data transmission unit
;Humidity and temperature sensors using 08M2 to read HS1101 capacitive sensor and DS18B20's and output serial data at 1200 baud via a 433 MHz radio link
;data is transmitted ~ every 34.5 seconds as 8 bytes following a preamble and identifier text message
;unit can accept calibration during programming to get approximately +/- 3% accuracy from humidity sensor
;sensor capacitance varies from approximately 163 pF at 0% RH to about 201 pF at 100% RH
;555 circuit is similar to that used in HH10D module, but works at 5V. Calibration factors work the same way
;temperature data is full 12 bits, rounded to nearest 0.1 deg C
#picaxe 08M2
symbol raw_humidity = w0 ;b0, b1
symbol raw_temperature = w1 ;b2, b3
symbol frequency_offset = w2 ;b4, b5
symbol relative_humidity = w3 ;b6, b7
symbol factor = w4 ;b8, b9
symbol sensitivity = w5 ;b10, b11
symbol offset = w6 ;b12, b13
symbol quotient = w7 ;b14, b15
symbol remainder = b16
symbol sign1 = b17
symbol whole_degrees1 = b18
symbol decimal_degrees1 = b19
symbol sign2 = b20
symbol whole_degrees2 = b21
symbol decimal_degrees2 = b22
symbol panel_voltage = b23
;Enter sensitivity and offset factors here from sensor calibration procedure
;offset is the measured RH sensor frequency at 0% RH obtained from testing in a dessicant chamber
;sensitivity is derived from the raw sensor value at 75.7% RH, using the formula (75.7 * 4096) / (0% RH frequency - 75.7% RH frequency)
;the sensor calibration spreadsheet, "Calibration factor calculation.xls" will derive the sensitivity factor. Use commented out code below for calibration
LET offset = 8112 ;frequency for 0% RH
LET sensitivity = 359 ;derived from formula above (75.7% is RH above saturated sodium chloride paste at 20 deg C)
;Calibration can also be checked using saturated magnesium chloride paste, which should give 33.1% RH at 20 deg C
;calibration chambers may take several hours at constant temperature for RH to stabilise. Temperature must be held within +/- 1 deg C during calibration
;main programme loop
main:
;Read humidity
count c.3,1000,raw_humidity ;read raw humidity value
frequency_offset = offset - raw_humidity ;subtract humidity frequency from 0% humidity frequency
factor = frequency_offset / 16 + 1 ;set a factor to reduce maximum value for rollover protection in next calculation
relative_humidity = 10 * frequency_offset / factor * sensitivity ;RH % x 10 for increased resolution
factor = 4096 / factor ;factor back down from rollover protection
relative_humidity = relative_humidity / factor
quotient = relative_humidity / 10
remainder = relative_humidity // 10 ;remainder used for round up/down detection
IF remainder >= 50 THEN LET relative_humidity = quotient + 1 ;rounds up/down, gives rounded RH integer in % to nearest 1%
ELSE LET relative_humidity = quotient
ENDIF
IF relative_humidity > 100 THEN LET relative_humidity = 100 ;corrects for tiny resolution error that might give false over-reading
ENDIF
;Read ground temperature
readtemp12 c.4,raw_temperature ;read raw ground temperature value
;convert 2's complement to decimal value and sign and round decimal degrees to nearest single decimal digit
;sets sign to ASCII 45 ("-") or space (" ", ASCII 32)
LET sign1 = 32 ;set sign to ASCII 32 = " " (space character)
IF raw_temperature > 64655 THEN ;-55 deg C = 64656
LET sign1 = 45 ;set sign to "-" for less than 0 deg C
raw_temperature = - raw_temperature
ENDIF
whole_degrees1 = raw_temperature / 16
decimal_degrees1 = raw_temperature * 4096 **10000 + 380 / 1000 ;returns whole degrees as integer and decimal degrees as correctly rounded remainder to 0.1 deg C
;Read air temperature
readtemp12 c.2,raw_temperature ;read raw air temperature value
;convert 2's complement to decimal value and sign and round decimal degrees to nearest single decimal digit
;sets sign to ASCII 45 ("-") or space (" ", ASCII 32)
LET sign2 = 32 ;set sign to ASCII 32 = " " (space character)
IF raw_temperature > 64655 THEN ;-55 deg C = 64656
LET sign2 = 45 ;set sign to "-" for less than 0 deg C
raw_temperature = - raw_temperature
ENDIF
whole_degrees2 = raw_temperature / 16
decimal_degrees2 = raw_temperature * 4096 **10000 + 380 / 1000 ;returns whole degrees as integer and decimal degrees as correctly rounded remainder to 0.1 deg C
;Read solar panel voltage
readadc c.1,panel_voltage ;~6.5 V = 1000 W/m² = 255 at ADC (100k + 30k divider)
;255 = 6.5 V (5V), so 1 bit = 19.6 mV
;output data as binary as 8 bytes, preceded by a preamble, at 1200 baud, 8 bit, no parity, 1 stop bit with "OUT" identifier text at start of data
;sequence of 85's wakes up the receiver and sets zero point for signal
;temperature, relative humidity and raw humidity value are transmitted as ASCII only for calibration purposes, as are CR and LF characters for terminal formatting
;data format is :
;sign1, whole_degrees1,decimal degrees1 is ground air temperature
;sign2,whole_degrees2,decimal_degrees2 is air temperature
;relative humidity
;panel voltage
setfreq m1
sertxd (85,85,85,85,"OUT",sign1,whole_degrees1,decimal_degrees1,sign2,whole_degrees2,decimal_degrees2,relative_humidity,panel_voltage)
;calibration code:
;sertxd (85,85,85,85,85,85,"OUT",sign1,whole_degrees1,decimal_degrees1,relative_humidity,#raw_humidity)
setfreq m4
SLEEP 1 ;go to low power mode for ~2.3 secs
goto main ;loop back to start of programme
END