113
+ − 1 ;=============================================================================
+ − 2 ;
+ − 3 ; File calibration.asm
+ − 4 ;
+ − 5 ; o2 sensor calibration subroutines
+ − 6 ;
+ − 7 ; Copyright (c) 2014, Heinrichs Weikamp, all right reserved.
+ − 8 ;=============================================================================
+ − 9
275
+ − 10 #include "hwos.inc"
113
+ − 11 #include "shared_definitions.h" ; Mailbox between c and asm
+ − 12 #include "math.inc"
+ − 13 #include "adc_lightsensor.inc"
+ − 14 #include "eeprom_rs232.inc"
+ − 15
+ − 16 calibrate CODE
+ − 17
192
+ − 18 global check_sensors ; Check O2 sensor thresholds for fallback and voting logic
145
+ − 19 check_sensors:
+ − 20 ; Check min_mv
+ − 21 movff o2_mv_sensor1+0, sub_a+0
+ − 22 movff o2_mv_sensor1+1, sub_a+1
+ − 23 movlw LOW min_mv
+ − 24 movwf sub_b+0
+ − 25 movlw HIGH min_mv
+ − 26 movwf sub_b+1
+ − 27 call sub16 ; sub_c = sub_a - sub_b
192
+ − 28 bsf use_O2_sensor1 ;=1: Use this sensor for deco
145
+ − 29 btfsc neg_flag
192
+ − 30 bcf use_O2_sensor1 ;=1: Use this sensor for deco
145
+ − 31
+ − 32 movff o2_mv_sensor2+0, sub_a+0
+ − 33 movff o2_mv_sensor2+1, sub_a+1
+ − 34 movlw LOW min_mv
+ − 35 movwf sub_b+0
+ − 36 movlw HIGH min_mv
+ − 37 movwf sub_b+1
+ − 38 call sub16 ; sub_c = sub_a - sub_b
192
+ − 39 bsf use_O2_sensor2 ;=1: Use this sensor for deco
145
+ − 40 btfsc neg_flag
192
+ − 41 bcf use_O2_sensor2 ;=1: Use this sensor for deco
145
+ − 42
+ − 43 movff o2_mv_sensor3+0, sub_a+0
+ − 44 movff o2_mv_sensor3+1, sub_a+1
+ − 45 movlw LOW min_mv
+ − 46 movwf sub_b+0
+ − 47 movlw HIGH min_mv
+ − 48 movwf sub_b+1
+ − 49 call sub16 ; sub_c = sub_a - sub_b
192
+ − 50 bsf use_O2_sensor3 ;=1: Use this sensor for deco
145
+ − 51 btfsc neg_flag
192
+ − 52 bcf use_O2_sensor3 ;=1: Use this sensor for deco
145
+ − 53 ; Check max_mv
+ − 54 movff o2_mv_sensor1+0, sub_a+0
+ − 55 movff o2_mv_sensor1+1, sub_a+1
+ − 56 movlw LOW max_mv
+ − 57 movwf sub_b+0
+ − 58 movlw HIGH max_mv
+ − 59 movwf sub_b+1
+ − 60 call sub16 ; sub_c = sub_a - sub_b
+ − 61 btfss neg_flag
192
+ − 62 bcf use_O2_sensor1 ;=1: Use this sensor for deco
145
+ − 63
+ − 64 movff o2_mv_sensor2+0, sub_a+0
+ − 65 movff o2_mv_sensor2+1, sub_a+1
+ − 66 movlw LOW max_mv
+ − 67 movwf sub_b+0
+ − 68 movlw HIGH max_mv
+ − 69 movwf sub_b+1
+ − 70 call sub16 ; sub_c = sub_a - sub_b
+ − 71 btfss neg_flag
192
+ − 72 bcf use_O2_sensor2 ;=1: Use this sensor for deco
145
+ − 73
+ − 74 movff o2_mv_sensor3+0, sub_a+0
+ − 75 movff o2_mv_sensor3+1, sub_a+1
+ − 76 movlw LOW max_mv
+ − 77 movwf sub_b+0
+ − 78 movlw HIGH max_mv
+ − 79 movwf sub_b+1
+ − 80 call sub16 ; sub_c = sub_a - sub_b
+ − 81 btfss neg_flag
192
+ − 82 bcf use_O2_sensor3 ;=1: Use this sensor for deco
145
+ − 83
+ − 84 btfss hud_connection_ok ;=1: HUD connection ok
189
+ − 85 bra check_sensor2 ; No HUD/Digital data
145
+ − 86
147
+ − 87 ; Copy disable flags from digital input
227
+ − 88 btfss sensor1_active
+ − 89 bcf use_O2_sensor1
+ − 90 btfss sensor2_active
+ − 91 bcf use_O2_sensor2
+ − 92 btfss sensor3_active
+ − 93 bcf use_O2_sensor3
192
+ − 94 bra check_sensor3 ; Check for voting logic
145
+ − 95
189
+ − 96 check_sensor2:
+ − 97 ; Copy disable flags from internal calibration routine
+ − 98 btfss sensor1_calibrated_ok
192
+ − 99 bcf use_O2_sensor1
189
+ − 100 btfss sensor2_calibrated_ok
192
+ − 101 bcf use_O2_sensor2
189
+ − 102 btfss sensor3_calibrated_ok
192
+ − 103 bcf use_O2_sensor3
+ − 104 check_sensor3: ; Check for voting logic
+ − 105 bsf voting_logic_sensor1
+ − 106 movff o2_ppo2_sensor1,temp1
+ − 107 rcall check_sensor_voting_common
+ − 108 incfsz WREG ; Was Wreg=255?
+ − 109 bcf voting_logic_sensor1 ; Yes, ignore this sensor
+ − 110 bsf voting_logic_sensor2
+ − 111 movff o2_ppo2_sensor2,temp1
+ − 112 rcall check_sensor_voting_common
+ − 113 incfsz WREG ; Was Wreg=255?
+ − 114 bcf voting_logic_sensor2 ; Yes, ignore this sensor
+ − 115 bsf voting_logic_sensor3
+ − 116 movff o2_ppo2_sensor3,temp1
+ − 117 rcall check_sensor_voting_common
+ − 118 incfsz WREG ; Was Wreg=255?
+ − 119 bcf voting_logic_sensor3 ; Yes, ignore this sensor
189
+ − 120 return
+ − 121
192
+ − 122
+ − 123 check_sensor_voting_common:
+ − 124 movf temp1,W
+ − 125 cpfsgt sensor_setpoint
+ − 126 bra check_sensor_voting_common2 ; temp1<sensor_setpoint
+ − 127 ; temp1>sensor_setpoint
+ − 128 movf temp1,W
+ − 129 subwf sensor_setpoint,W
+ − 130 movwf temp1
+ − 131 check_sensor_voting_common1:
+ − 132 movlw sensor_voting_logic_threshold ; Threshold in 0.01bar
+ − 133 cpfsgt temp1
+ − 134 retlw .255 ; Within range
+ − 135 retlw .0 ; Out of range
+ − 136 check_sensor_voting_common2:
+ − 137 ; temp1<sensor_setpoint
+ − 138 movf sensor_setpoint,W
+ − 139 subwf temp1,F
+ − 140 bra check_sensor_voting_common1
+ − 141
113
+ − 142 global calibrate_mix
+ − 143 calibrate_mix:
+ − 144 ; calibrate S8 HUD
+ − 145 btfss s8_digital ; S8 Digital?
+ − 146 bra calibrate_mix2 ; No
+ − 147
189
+ − 148 ; Yes, calibrate any S8-connected HUD
113
+ − 149 clrf temp1 ; Chksum
+ − 150 movlw 0xAA ; Start Byte
+ − 151 addwf temp1,F
+ − 152 movff WREG,TXREG2
+ − 153 call rs232_wait_tx2
+ − 154
+ − 155 movlw 0x31 ; Calibrate
+ − 156 addwf temp1,F
+ − 157 movff WREG,TXREG2
+ − 158 call rs232_wait_tx2
+ − 159
+ − 160 movff opt_calibration_O2_ratio,WREG ; Calibration gas %O2
+ − 161 addwf temp1,F
+ − 162 movff WREG,TXREG2
+ − 163 call rs232_wait_tx2
+ − 164
+ − 165 movff amb_pressure+0,WREG ; Ambient pressure
+ − 166 addwf temp1,F
+ − 167 movff WREG,TXREG2
+ − 168 call rs232_wait_tx2
+ − 169 movff amb_pressure+1,WREG
+ − 170 addwf temp1,F
+ − 171 movff WREG,TXREG2
+ − 172 call rs232_wait_tx2
+ − 173
+ − 174 movff temp1,TXREG2 ; Chksum
+ − 175 call rs232_wait_tx2
+ − 176
+ − 177 calibrate_mix2:
+ − 178 movff opt_calibration_O2_ratio,WREG ; Calibration gas %O2
+ − 179 mullw .100
+ − 180 movff PRODL,xA+0
+ − 181 movff PRODH,xA+1
+ − 182 ; (%O2*100)*[ambient,mbar]/100 -> xC
+ − 183 movff amb_pressure+0,xB+0
+ − 184 movff amb_pressure+1,xB+1
+ − 185 call mult16x16 ;xA*xB=xC
+ − 186 movlw LOW .100
+ − 187 movwf xB+0
+ − 188 movlw HIGH .100
+ − 189 movwf xB+1
+ − 190 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 191 movff o2_mv_sensor1+0,xB+0
+ − 192 movff o2_mv_sensor1+1,xB+1
+ − 193 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 194 ; xC= ppO2/mV
+ − 195 movff xC+0,opt_x_s1+0
+ − 196 movff xC+1,opt_x_s1+1 ; Factor for Sensor1
+ − 197
+ − 198 movff opt_calibration_O2_ratio,WREG ; Calibration gas %O2
+ − 199 mullw .100
+ − 200 movff PRODL,xA+0
+ − 201 movff PRODH,xA+1
+ − 202 ; (%O2*100)*[ambient,mbar]/100 -> xC
+ − 203 movff amb_pressure+0,xB+0
+ − 204 movff amb_pressure+1,xB+1
+ − 205 call mult16x16 ;xA*xB=xC
+ − 206 movlw LOW .100
+ − 207 movwf xB+0
+ − 208 movlw HIGH .100
+ − 209 movwf xB+1
+ − 210 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 211 movff o2_mv_sensor2+0,xB+0
+ − 212 movff o2_mv_sensor2+1,xB+1
+ − 213 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 214 ; xC= ppO2/mV
+ − 215 movff xC+0,opt_x_s2+0
+ − 216 movff xC+1,opt_x_s2+1 ; Factor for Sensor2
+ − 217
+ − 218 movff opt_calibration_O2_ratio,WREG ; Calibration gas %O2
+ − 219 mullw .100
+ − 220 movff PRODL,xA+0
+ − 221 movff PRODH,xA+1
+ − 222 ; (%O2*100)*[ambient,mbar]/100 -> xC
+ − 223 movff amb_pressure+0,xB+0
+ − 224 movff amb_pressure+1,xB+1
+ − 225 call mult16x16 ;xA*xB=xC
+ − 226 movlw LOW .100
+ − 227 movwf xB+0
+ − 228 movlw HIGH .100
+ − 229 movwf xB+1
+ − 230 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 231 movff o2_mv_sensor3+0,xB+0
+ − 232 movff o2_mv_sensor3+1,xB+1
+ − 233 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 234 ; xC= ppO2/mV
+ − 235 movff xC+0,opt_x_s3+0
+ − 236 movff xC+1,opt_x_s3+1 ; Factor for Sensor3
+ − 237
189
+ − 238 bsf sensor1_calibrated_ok
+ − 239 bsf sensor2_calibrated_ok
+ − 240 bsf sensor3_calibrated_ok ; Set flags prior check
+ − 241 rcall check_sensors ; Check O2 sensor thresholds min_mv and max_mv and set use_02_sensorX flags
+ − 242 ; initialise internal calibration flags
192
+ − 243 btfss use_O2_sensor1 ; Sensor out of range?
189
+ − 244 bcf sensor1_calibrated_ok ; Yes, disable this sensor
192
+ − 245 btfss use_O2_sensor2 ; Sensor out of range?
189
+ − 246 bcf sensor2_calibrated_ok ; Yes, disable this sensor
192
+ − 247 btfss use_O2_sensor3 ; Sensor out of range?
189
+ − 248 bcf sensor3_calibrated_ok ; Yes, disable this sensor
113
+ − 249
+ − 250 ; When no sensor is found, enable all three to show error state
192
+ − 251 btfsc use_O2_sensor1
113
+ − 252 return
192
+ − 253 btfsc use_O2_sensor2
113
+ − 254 return
192
+ − 255 btfsc use_O2_sensor3
113
+ − 256 return
192
+ − 257 bsf use_O2_sensor1
+ − 258 bsf use_O2_sensor2
+ − 259 bsf use_O2_sensor3
113
+ − 260 ; Clear factors
+ − 261 banksel opt_x_s1+0
+ − 262 clrf opt_x_s1+0
+ − 263 clrf opt_x_s1+1
+ − 264 clrf opt_x_s2+0
+ − 265 clrf opt_x_s2+1
+ − 266 clrf opt_x_s3+0
+ − 267 clrf opt_x_s3+1
+ − 268 banksel common
+ − 269 return
+ − 270
+ − 271 compute_ppo2_analog:
+ − 272 call get_analog_inputs
+ − 273 bra compute_ppo2_common
+ − 274
+ − 275 global compute_ppo2 ; compute mv_sensorX and ppo2_sensorX arrays
+ − 276 compute_ppo2:
236
+ − 277 btfss analog_o2_input ; cR hardware?
113
+ − 278 return ; No
+ − 279
+ − 280 btfss s8_digital ; =1: Digital I/O
+ − 281 bra compute_ppo2_analog ; use analog
+ − 282
+ − 283 ; use digital
+ − 284 btfss new_s8_data_available ; =1: New data frame recieved
+ − 285 return
+ − 286 call compute_mvolts_for_all_sensors
+ − 287
+ − 288 compute_ppo2_common:
+ − 289 ; o2_mv_sensor1:2 * opt_x_s1:2 = o2_ppo2_sensor1/10000
+ − 290 movff o2_mv_sensor1+0,xA+0
+ − 291 movff o2_mv_sensor1+1,xA+1
+ − 292 movff opt_x_s1+0,xB+0
+ − 293 movff opt_x_s1+1,xB+1
+ − 294 call mult16x16 ;xA:2*xB:2=xC:4
+ − 295 movlw LOW .1000
+ − 296 movwf xB+0
+ − 297 movlw HIGH .1000
+ − 298 movwf xB+1
+ − 299 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 300 movlw d'1'
+ − 301 addwf xC+0,F
+ − 302 movlw d'0'
+ − 303 addwfc xC+1,F
190
+ − 304 tstfsz xC+1 ; ppO2 is higher then 2.55bar?
+ − 305 setf xC+0 ; Yes.
+ − 306 movff xC+0,o2_ppo2_sensor1 ; result in 0.01bar
192
+ − 307 ; ; Set to zero if sensor is not active!
+ − 308 ; btfss use_O2_sensor1
+ − 309 ; clrf o2_ppo2_sensor1
113
+ − 310
+ − 311 ; o2_mv_sensor2:2 * opt_x_s1:2 = o2_ppo2_sensor2/10000
+ − 312 movff o2_mv_sensor2+0,xA+0
+ − 313 movff o2_mv_sensor2+1,xA+1
+ − 314 movff opt_x_s2+0,xB+0
+ − 315 movff opt_x_s2+1,xB+1
+ − 316 call mult16x16 ;xA:2*xB:2=xC:4
+ − 317 movlw LOW .1000
+ − 318 movwf xB+0
+ − 319 movlw HIGH .1000
+ − 320 movwf xB+1
+ − 321 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 322 movlw d'1'
+ − 323 addwf xC+0,F
+ − 324 movlw d'0'
+ − 325 addwfc xC+1,F
190
+ − 326 tstfsz xC+1 ; ppO2 is higher then 2.55bar?
+ − 327 setf xC+0 ; Yes.
+ − 328 movff xC+0,o2_ppo2_sensor2 ; result in 0.01bar
192
+ − 329 ; ; Set to zero if sensor is not active!
+ − 330 ; btfss use_O2_sensor2
+ − 331 ; clrf o2_ppo2_sensor2
113
+ − 332
+ − 333 ; o2_mv_sensor3:2 * opt_x_s1:2 = o2_ppo2_sensor3/10000
+ − 334 movff o2_mv_sensor3+0,xA+0
+ − 335 movff o2_mv_sensor3+1,xA+1
+ − 336 movff opt_x_s3+0,xB+0
+ − 337 movff opt_x_s3+1,xB+1
+ − 338 call mult16x16 ;xA:2*xB:2=xC:4
+ − 339 movlw LOW .1000
+ − 340 movwf xB+0
+ − 341 movlw HIGH .1000
+ − 342 movwf xB+1
+ − 343 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 344 movlw d'1'
+ − 345 addwf xC+0,F
+ − 346 movlw d'0'
+ − 347 addwfc xC+1,F
190
+ − 348 tstfsz xC+1 ; ppO2 is higher then 2.55bar?
+ − 349 setf xC+0 ; Yes.
+ − 350 movff xC+0,o2_ppo2_sensor3 ; result in 0.01bar
192
+ − 351 ; ; Set to zero if sensor is not active!
+ − 352 ; btfss use_O2_sensor3
+ − 353 ; clrf o2_ppo2_sensor3
113
+ − 354 return ; Done.
+ − 355
+ − 356
+ − 357 compute_mvolts_for_all_sensors: ; Compute mV or all sensors (S8 Mode)
+ − 358 ; compute AD results in 100µV steps (16bit/sensor)
+ − 359 ; 24bit AD result is in 244,1406541nV
+ − 360 ; Devide 24bit value through 409,5999512 -> 410 (0,01% error)
+ − 361 #DEFINE ad2mv_factor .410
+ − 362 ; Sensor 1
+ − 363 clrf xC+3
268
+ − 364 movff s8_rawdata_sensor1+2,xC+2
+ − 365 movff s8_rawdata_sensor1+1,xC+1
+ − 366 movff s8_rawdata_sensor1+0,xC+0
113
+ − 367 movlw LOW ad2mv_factor
+ − 368 movwf xB+0
+ − 369 movlw HIGH ad2mv_factor
+ − 370 movwf xB+1
+ − 371 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 372 movff xC+1,o2_mv_sensor1+1
+ − 373 movff xC+0,o2_mv_sensor1+0 ; in 100uV steps
+ − 374 ; Sensor 2
+ − 375 clrf xC+3
268
+ − 376 movff s8_rawdata_sensor2+2,xC+2
+ − 377 movff s8_rawdata_sensor2+1,xC+1
+ − 378 movff s8_rawdata_sensor2+0,xC+0
113
+ − 379 movlw LOW ad2mv_factor
+ − 380 movwf xB+0
+ − 381 movlw HIGH ad2mv_factor
+ − 382 movwf xB+1
+ − 383 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 384 movff xC+1,o2_mv_sensor2+1
+ − 385 movff xC+0,o2_mv_sensor2+0 ; in 100uV steps
+ − 386 ; Sensor 3
+ − 387 clrf xC+3
268
+ − 388 movff s8_rawdata_sensor3+2,xC+2
+ − 389 movff s8_rawdata_sensor3+1,xC+1
+ − 390 movff s8_rawdata_sensor3+0,xC+0
113
+ − 391 movlw LOW ad2mv_factor
+ − 392 movwf xB+0
+ − 393 movlw HIGH ad2mv_factor
+ − 394 movwf xB+1
+ − 395 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
+ − 396 movff xC+1,o2_mv_sensor3+1
+ − 397 movff xC+0,o2_mv_sensor3+0 ; in 100uV steps
+ − 398
+ − 399 bcf new_s8_data_available ; Clear flag
+ − 400 return ; Done.
+ − 401
352
+ − 402 global transmit_setpoint ; Transmit current setpoint from WREG (in cbar) to external electronics
+ − 403 transmit_setpoint:
+ − 404 btfss s8_digital ; S8 Digital?
+ − 405 return ; No, ignore
+ − 406
+ − 407 ; Yes, transmit setpoint from WREG
+ − 408 movwf temp2 ; Store setpoint
+ − 409 clrf temp1 ; Chksum
+ − 410 movlw 0xAA ; Start Byte
+ − 411 addwf temp1,F
+ − 412 movff WREG,TXREG2
+ − 413 call rs232_wait_tx2
+ − 414
+ − 415 movlw 0x60 ; New SP
+ − 416 addwf temp1,F
+ − 417 movff WREG,TXREG2
+ − 418 call rs232_wait_tx2
+ − 419
+ − 420 movff temp2,WREG ; SP in cbar
+ − 421 addwf temp1,F
+ − 422 movff WREG,TXREG2
+ − 423 call rs232_wait_tx2
+ − 424
+ − 425 movff temp1,TXREG2 ; Chksum
+ − 426 call rs232_wait_tx2
+ − 427 return
113
+ − 428
+ − 429
+ − 430 END