'm168-test-capacitor-rc-timing-direct.bas ' v0.02 - Removed redundant variables and converte average ' to a loop. This version seems to provide very ' stable readings for a single sensor and is ' smaller than v0.01 ' ' v0.03 - Added eram storage of config paramters ' - Added support for 7 sensors ' - Added support for internal configuration ' Direct read capacitive humidity sensor from Micro controller. ' which reduces the parts costs. The basic capacitive sensors start ' at about $3.50 while the voltage or freq out tend to start at $15 ' and run to over $30. My favorite is the SHT11 and SHT75 but they ' start at $30. The same approach can be used ' to sense change in capacitance for other circuits ' such as strain gauges. ' ' This design provides easy field program calibration capability through ' serial line which the other sensors do not. Simply send command to ' calibrate and current reading near the sensor. It will compare that to ' current values and save reading in eprom. Allows for easy field ' calibaration. ' ' Tested on Mega168 ' Probably better implemented with ' a AVRTiny which could be mounted right on the sensor and then hold ' 1 wire conversation back to master controller. ' ' ' HCH sensor typical response curve 298Pf at 0%RH upto 358pf @ 100%. Interestingly ' got numbers very close to this range from loop counter with 10M resistor. ' http://www.honeywell-sensor.com.cn/prodinfo/sensor_humidity_moisture/datasheet/HCH-1000.pdf ' http://mouser.com/ProductDetail/Honeywell/HCH-1000-002/?qs=yJVtgANCw01Gp3IHDXhPcA%3d%3d ' ' ' ****** ' **** Enhancments *** ' ****** ' TODO: Convert simple low, High readings to an array so we find the first ' last low reading which is lower than the current reading. Allow upto 5 ' calibration settings per sensor. May be able to hard code these for ' Magnesium Chloride = 32.78, sodium Chloride 75.3, potassium nitrate 93.5, ' and water 100% but in the field I may be forced to use a recently ' calibrated sensor and use of ambient so should store the percentage with ' the reading number and treat as simple array. How to store an array in ' the software? Would be nice to offer immediate calibrate read ' or delayed. If The read % is the same then override Should wait until I ' get 5 identical reads for calibration. also need to be able to clear ' the read. Should set the calibration for slot # eg: s0 is for lowest ' calibration while sl5 is for the highest. Not getting 5 reads in a row ' seems to be low but we normally only see a 1 digit variration +- once ' stabilized so we have the choice of averaging 20 reads or taking the ' first one where we get 5 out of ten of the same reading. ' ' TODO: Add inbound commands to run average of 33% salt solution and store ' in non volatile memory. second button for 76% or 100% solution. ' change calculator to use NV memory to retain. ' TODO: Add pin 1..7 to allow any additional pins on port D to ' to act as readers. Allow these to be multi-plexed by passing ' in parm to function. Need to figure out how to pad pind.x as parm. ' TODO: Convert all to word calculations and scale up by 100 to retain decimals ' that way eliminate need for floating point at all. ' TODO: Add 1 leg of temp sensor back into the solution to allow temperature ' compensation. '$regfile = "m64def.dat" $regfile = "m16def.dat" $crystal = 8000000 $hwstack = 64 ' default use 32 for the hardware stack $swstack = 60 ' default use 10 for the SW stack $framesize = 80 ' default use 40 for the frame space 'eprom storage Dim Empty_byte As Eram byte at 0 '1b Dim sensor_id as Eram Byte '1b Dim sens_read_per_hour as eram word '2b 'attempt this many reads per 'hour on all active sensors. maximum ' is alloated at about 1 read per 2 ' seconds. Dim sen_calib(70) as Eram word '140b ' 5 slots * (1-percent, 1-cnt) * 7 sensors 'pndx = slotid * 2 'rndx = slotid * 2 + 1 ' where slot id is numbered 0..6 ' convention is that each slot contains the reading for the next ' higher percentage reading and that the empty slots are skipped. ' lowest slot will contain highest lowest calibration reading ' highest slot will contain highes calibration reading dim sens_active(7) as eram byte '7b ' sensor acive or inacive array determines if the sensor ' is read. dim sens_alarm_low(7) as eram byte '7b ' Array of low and high alarms. dim sens_alarm_high(7) as eram byte '7b ' if the sensor goes above or below the alarm specified ' the raise IO pin for that sensor and send out the ' alarm command information. Also send out the ' recover when it comes back in range. ' s(n).low = sens_larm( dim tfloat as single dim tsingle as single dim tlong as long dim tword as word dim r_dif as single dim p_dif as single dim rdif_per_perc as single Declare Function conv_count_to_humidity(cnt as Word, byval low_r as word, byval low_p as word, cnt_per_perc as Single) As Single Declare Function read_humdity_avg(byval sens_num as byte) as Word Declare Function read_humid(byval sens_num as byte) as Word declare Function read_humid_s0() As Word declare Function read_humid_s1() As Word declare Function read_humid_s2() As Word declare Function read_humid_s3() As Word declare Function read_humid_s4() As Word declare Function read_humid_s5() As Word declare Function read_humid_s6() As Word 'declare Function test_pass_pin(byval aPin as byte) as word Open "comd.1:9600,8,N,1,inverted" For Output As #1 Open "comd.0:9600,8,N,1,inverted" For Input As #2 Const bon = 1 Const boff = 0 Config Portd.5 = Output Config Portd.4 = input config portd.6 = output humid_rc_charge alias portd.5 humid_rc_read_s0 alias pind.0 humid_rc_read_s1 alias pind.1 humid_rc_read_s2 alias pind.2 humid_rc_read_s3 alias pind.3 humid_rc_read_s4 alias pind.4 humid_rc_read_s5 alias pind.5 humid_rc_read_s6 alias pind.6 ' Pin 7 reserved for dricing the power humid_led alias portd.6 humid_rc_charge = boff const chi_r = 1121 ' count reading at high humidity const chi_p = 100 ' percentage reading taken at 'const chi_r = 1099 ' count reading at high humidity 'const chi_p = 75.3 ' percentage reading taken at 'const lo_r = 1045 ' count reading at low humidity 'const lo_p = 33 ' RH percentage at low humidity reading const clo_r = 1021 ' count reading at low humidity const clo_p = 42 ' RH percentage at low humidity reading const clo_no_sens = 400 ' if reading is lower than this assume no sensor present ' no sensor is typically about 19 r_dif = chi_r - clo_r p_dif = chi_p - clo_p rdif_per_perc = r_dif / p_dif print #1, "m168-test-capacitor-rc-timing-direct.v.02.bas" print #1, "cnt per percent = "; rdif_per_perc Dim calc_p as single 'tword = test_pass_pin(pind.5) Do tword = read_humdity_avg(0) print #1, " 2avg="; tword; calc_p = conv_count_to_humidity(tword, clo_r, clo_p, rdif_per_perc) print #1, " avg%=";Fusing(calc_p , "-###.#") Waitms 500 Loop Function read_humdity_avg(sens_num) as Word ' add another layer of averages const num_avg = 9 dim ci as byte dim tread as long tread = 0 for ci = 1 to num_avg tword = read_humid(sens_num) tread = tread + tword next ci tread = tread / num_avg read_humdity_avg = tread 'waitms 300 end function 'Function test_pass_pin(byval aPin as byte) as word ' dim tt as byte 'end function Function conv_count_to_humidity(cnt as Word, byval low_r as word, byval low_p as word, cnt_per_perc as Single) As Single 'Convert Avg reading to Percentage dim ddelta as single dim dmult as single dim tperc as single ddelta = cnt - low_r ' how far are we above low calibration reading dmult = ddelta / cnt_per_perc ' how many units of percentage dose delta reading work out to. tperc = low_p + dmult conv_count_to_humidity = tperc end function const humid_num_to_read = 12 const humid_wait_between_read = 4 Dim humid_ri as Byte ' index 2 Dim humid_tot_read as Word ' accumulator 2 Dim humid_tcnt as Word ' Would have preferred to use the bit number as a parm ' so we could pass in the alias for portd.pin4 but ' can not figure out how to get the compiler to do this. function read_humid(sens_num as byte) as word ' Take 1 waste reading to setup the capacitor ' state the exact same as it would be in the ' averaging loop. Otherwise the cap may be ' more fully discharged and could result in ' a lower first read value. humid_tcnt = read_humid_s0() select case sens_num case 0: humid_tcnt = read_humid_s0() case 1: humid_tcnt = read_humid_s1() case 2: humid_tcnt = read_humid_s2() case 3: humid_tcnt = read_humid_s3() case 4: humid_tcnt = read_humid_s4() end select ' Take multiple readings in a row and average them. ' for any single reading. humid_tot_read = 0 for humid_ri = 1 to humid_num_to_read select case sens_num case 0: humid_tcnt = read_humid_s0() case 1: humid_tcnt = read_humid_s1() case 2: humid_tcnt = read_humid_s2() case 3: humid_tcnt = read_humid_s3() case 4: humid_tcnt = read_humid_s4() end select humid_tot_read = humid_tot_read + humid_tcnt next humid_ri humid_tot_read = humid_tot_read / humid_num_to_read read_humid = humid_tot_read end function sub humid_set_sensor_active(sensor_num as byte) end sub sub humid_set_sensor_deactive(sensor_num as byte) end sub sub humid_set_sensor_alarm_hi(sensor_num as byte, alarm_perc as word) end sub sub humid_set_sensor_alarm_lo(sensor_num as byte, alarm_perc as word) end sub ' return alarm threashol value for hi sensor ' or 0 if not set function humid_sensor_alarm_hi(sensor_num as byte) end function ' return alarm threashold for low alarm or 0 if not set function humid_sensor_alarm_lo(sensor_num as byte) end function ' Calibrate multiple sensors to the specified ' percentage. This is used in the case when ' all the sensors are placed in the same chamber ' and need to all be calibrated for that percentage solution. sub humid_calibrate_sensors(slot_num as byte, perc_in as byte) end sub ' Read the sensor and until we get 10 readings where the ' net delta in readings is less than 1 count unit +- ' then average the next 20 readings ans save the result ' in configuration slot for that sensor. sub humid_calibrate_sensor(sensor_num as byte, slot_num as byte, perc_in as word) end sub ' Loop through the slots and find the first highest ' low reading which is less than the reading in ' and the lowest high reading which is higher than ' the Function humid_find_slots(sensor_num as byte, reading as word) end function ' ********************* ' *** Primitive sensor reading ' ********************* '***** '**** Would prefer to pass the bit number into the read_humdiity_sensor '*** but can not figure out how to get Bascom to accept this. '***** Function read_humid_s0() As Word reset humid_rc_charge Bitwait humid_rc_read_s0, reset ' wait until read low waitms humid_wait_between_read ' Give time to discharge thorugh diode. humid_tcnt = 0 set humid_led set humid_rc_charge while humid_rc_read_s0 < bon ' Manual loop to see how long it takes to humid_tcnt = humid_tcnt + 1 ' Charge the capacitor wend reset humid_rc_charge reset humid_led read_humid_s0 = humid_tcnt end function '***** '**** Would prefer to pass the bit number into the read_humdiity_sensor '*** but can not figure out how to get Bascom to accept this. '***** Function read_humid_s1() As Word reset humid_rc_charge Bitwait humid_rc_read_s1, reset ' wait until read low waitms humid_wait_between_read ' Give time to discharge thorugh diode. humid_tcnt = 0 set humid_led set humid_rc_charge while humid_rc_read_s1 < bon ' Manual loop to see how long it takes to humid_tcnt = humid_tcnt + 1 ' Charge the capacitor wend reset humid_rc_charge reset humid_led read_humid_s1 = humid_tcnt end function '***** '**** Would prefer to pass the bit number into the read_humdiity_sensor '*** but can not figure out how to get Bascom to accept this. '***** Function read_humid_s2() As Word reset humid_rc_charge Bitwait humid_rc_read_s2, reset ' wait until read low waitms humid_wait_between_read ' Give time to discharge thorugh diode. humid_tcnt = 0 set humid_led set humid_rc_charge while humid_rc_read_s2 < bon ' Manual loop to see how long it takes to humid_tcnt = humid_tcnt + 1 ' Charge the capacitor wend reset humid_rc_charge reset humid_led read_humid_s2 = humid_tcnt end function '***** '**** Would prefer to pass the bit number into the read_humdiity_sensor '*** but can not figure out how to get Bascom to accept this. '***** Function read_humid_s3() As Word reset humid_rc_charge Bitwait humid_rc_read_s3, reset ' wait until read low waitms humid_wait_between_read ' Give time to discharge thorugh diode. humid_tcnt = 0 set humid_led set humid_rc_charge while humid_rc_read_s3 < bon ' Manual loop to see how long it takes to humid_tcnt = humid_tcnt + 1 ' Charge the capacitor wend reset humid_rc_charge reset humid_led read_humid_s3 = humid_tcnt end function '***** '**** Would prefer to pass the bit number into the read_humdiity_sensor '*** but can not figure out how to get Bascom to accept this. '***** Function read_humid_s4() As Word reset humid_rc_charge Bitwait humid_rc_read_s4, reset ' wait until read low waitms humid_wait_between_read ' Give time to discharge thorugh diode. humid_tcnt = 0 set humid_led set humid_rc_charge while humid_rc_read_s4 < bon ' Manual loop to see how long it takes to humid_tcnt = humid_tcnt + 1 ' Charge the capacitor wend reset humid_rc_charge reset humid_led read_humid_s4 = humid_tcnt end function '***** '**** Would prefer to pass the bit number into the read_humdiity_sensor '*** but can not figure out how to get Bascom to accept this. '***** Function read_humid_s5() As Word reset humid_rc_charge Bitwait humid_rc_read_s5, reset ' wait until read low waitms humid_wait_between_read ' Give time to discharge thorugh diode. humid_tcnt = 0 set humid_led set humid_rc_charge while humid_rc_read_s5 < bon ' Manual loop to see how long it takes to humid_tcnt = humid_tcnt + 1 ' Charge the capacitor wend reset humid_rc_charge reset humid_led read_humid_s5 = humid_tcnt end function '***** '**** Would prefer to pass the bit number into the read_humdiity_sensor '*** but can not figure out how to get Bascom to accept this. '***** Function read_humid_s6() As Word reset humid_rc_charge Bitwait humid_rc_read_s6, reset ' wait until read low waitms humid_wait_between_read ' Give time to discharge thorugh diode. humid_tcnt = 0 set humid_led set humid_rc_charge while humid_rc_read_s6 < bon ' Manual loop to see how long it takes to humid_tcnt = humid_tcnt + 1 ' Charge the capacitor wend reset humid_rc_charge reset humid_led read_humid_s6 = humid_tcnt end function