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
|
448
|
10 #include "hwos.inc"
|
|
11 #include "shared_definitions.h" ; Mailbox between c and asm
|
|
12 #include "math.inc"
|
113
|
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
|
448
|
185 rcall calibrate_mix2_helper
|
113
|
186 movff o2_mv_sensor1+0,xB+0
|
|
187 movff o2_mv_sensor1+1,xB+1
|
|
188 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
189 ; xC= ppO2/mV
|
|
190 movff xC+0,opt_x_s1+0
|
|
191 movff xC+1,opt_x_s1+1 ; Factor for Sensor1
|
|
192
|
|
193 movff opt_calibration_O2_ratio,WREG ; Calibration gas %O2
|
|
194 mullw .100
|
|
195 movff PRODL,xA+0
|
|
196 movff PRODH,xA+1
|
|
197 ; (%O2*100)*[ambient,mbar]/100 -> xC
|
|
198 movff amb_pressure+0,xB+0
|
|
199 movff amb_pressure+1,xB+1
|
448
|
200 rcall calibrate_mix2_helper
|
113
|
201 movff o2_mv_sensor2+0,xB+0
|
|
202 movff o2_mv_sensor2+1,xB+1
|
|
203 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
204 ; xC= ppO2/mV
|
|
205 movff xC+0,opt_x_s2+0
|
|
206 movff xC+1,opt_x_s2+1 ; Factor for Sensor2
|
|
207
|
|
208 movff opt_calibration_O2_ratio,WREG ; Calibration gas %O2
|
|
209 mullw .100
|
|
210 movff PRODL,xA+0
|
|
211 movff PRODH,xA+1
|
|
212 ; (%O2*100)*[ambient,mbar]/100 -> xC
|
|
213 movff amb_pressure+0,xB+0
|
|
214 movff amb_pressure+1,xB+1
|
448
|
215 rcall calibrate_mix2_helper
|
113
|
216 movff o2_mv_sensor3+0,xB+0
|
|
217 movff o2_mv_sensor3+1,xB+1
|
|
218 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
219 ; xC= ppO2/mV
|
|
220 movff xC+0,opt_x_s3+0
|
|
221 movff xC+1,opt_x_s3+1 ; Factor for Sensor3
|
|
222
|
189
|
223 bsf sensor1_calibrated_ok
|
|
224 bsf sensor2_calibrated_ok
|
|
225 bsf sensor3_calibrated_ok ; Set flags prior check
|
|
226 rcall check_sensors ; Check O2 sensor thresholds min_mv and max_mv and set use_02_sensorX flags
|
|
227 ; initialise internal calibration flags
|
192
|
228 btfss use_O2_sensor1 ; Sensor out of range?
|
189
|
229 bcf sensor1_calibrated_ok ; Yes, disable this sensor
|
192
|
230 btfss use_O2_sensor2 ; Sensor out of range?
|
189
|
231 bcf sensor2_calibrated_ok ; Yes, disable this sensor
|
192
|
232 btfss use_O2_sensor3 ; Sensor out of range?
|
189
|
233 bcf sensor3_calibrated_ok ; Yes, disable this sensor
|
113
|
234
|
|
235 ; When no sensor is found, enable all three to show error state
|
192
|
236 btfsc use_O2_sensor1
|
113
|
237 return
|
192
|
238 btfsc use_O2_sensor2
|
113
|
239 return
|
192
|
240 btfsc use_O2_sensor3
|
113
|
241 return
|
192
|
242 bsf use_O2_sensor1
|
|
243 bsf use_O2_sensor2
|
|
244 bsf use_O2_sensor3
|
113
|
245 ; Clear factors
|
|
246 banksel opt_x_s1+0
|
|
247 clrf opt_x_s1+0
|
|
248 clrf opt_x_s1+1
|
|
249 clrf opt_x_s2+0
|
|
250 clrf opt_x_s2+1
|
|
251 clrf opt_x_s3+0
|
|
252 clrf opt_x_s3+1
|
|
253 banksel common
|
|
254 return
|
|
255
|
448
|
256 calibrate_mix2_helper:
|
|
257 call mult16x16 ;xA*xB=xC
|
|
258 movlw LOW .100
|
|
259 movwf xB+0
|
|
260 movlw HIGH .100
|
|
261 movwf xB+1
|
|
262 goto div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder (And return)
|
|
263
|
|
264
|
113
|
265 compute_ppo2_analog:
|
|
266 call get_analog_inputs
|
|
267 bra compute_ppo2_common
|
|
268
|
|
269 global compute_ppo2 ; compute mv_sensorX and ppo2_sensorX arrays
|
|
270 compute_ppo2:
|
236
|
271 btfss analog_o2_input ; cR hardware?
|
113
|
272 return ; No
|
|
273
|
|
274 btfss s8_digital ; =1: Digital I/O
|
|
275 bra compute_ppo2_analog ; use analog
|
|
276
|
|
277 ; use digital
|
|
278 btfss new_s8_data_available ; =1: New data frame recieved
|
|
279 return
|
448
|
280 rcall compute_mvolts_for_all_sensors
|
113
|
281
|
|
282 compute_ppo2_common:
|
|
283 ; o2_mv_sensor1:2 * opt_x_s1:2 = o2_ppo2_sensor1/10000
|
|
284 movff o2_mv_sensor1+0,xA+0
|
|
285 movff o2_mv_sensor1+1,xA+1
|
|
286 movff opt_x_s1+0,xB+0
|
|
287 movff opt_x_s1+1,xB+1
|
448
|
288 rcall compute_ppo2_common_helper
|
190
|
289 movff xC+0,o2_ppo2_sensor1 ; result in 0.01bar
|
192
|
290 ; ; Set to zero if sensor is not active!
|
|
291 ; btfss use_O2_sensor1
|
|
292 ; clrf o2_ppo2_sensor1
|
113
|
293
|
|
294 ; o2_mv_sensor2:2 * opt_x_s1:2 = o2_ppo2_sensor2/10000
|
|
295 movff o2_mv_sensor2+0,xA+0
|
|
296 movff o2_mv_sensor2+1,xA+1
|
|
297 movff opt_x_s2+0,xB+0
|
|
298 movff opt_x_s2+1,xB+1
|
448
|
299 rcall compute_ppo2_common_helper
|
190
|
300 movff xC+0,o2_ppo2_sensor2 ; result in 0.01bar
|
192
|
301 ; ; Set to zero if sensor is not active!
|
|
302 ; btfss use_O2_sensor2
|
|
303 ; clrf o2_ppo2_sensor2
|
113
|
304
|
|
305 ; o2_mv_sensor3:2 * opt_x_s1:2 = o2_ppo2_sensor3/10000
|
|
306 movff o2_mv_sensor3+0,xA+0
|
|
307 movff o2_mv_sensor3+1,xA+1
|
|
308 movff opt_x_s3+0,xB+0
|
|
309 movff opt_x_s3+1,xB+1
|
448
|
310 rcall compute_ppo2_common_helper
|
|
311 movff xC+0,o2_ppo2_sensor3 ; result in 0.01bar
|
|
312 ; ; Set to zero if sensor is not active!
|
|
313 ; btfss use_O2_sensor3
|
|
314 ; clrf o2_ppo2_sensor3
|
|
315 return ; Done.
|
|
316
|
|
317 compute_ppo2_common_helper:
|
113
|
318 call mult16x16 ;xA:2*xB:2=xC:4
|
|
319 movlw LOW .1000
|
|
320 movwf xB+0
|
448
|
321 movlw HIGH .1000
|
113
|
322 movwf xB+1
|
|
323 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
324 movlw d'1'
|
|
325 addwf xC+0,F
|
|
326 movlw d'0'
|
|
327 addwfc xC+1,F
|
448
|
328 tstfsz xC+1 ; ppO2 is higher then 2.55bar?
|
|
329 setf xC+0 ; Yes.
|
|
330 return
|
113
|
331
|
|
332 compute_mvolts_for_all_sensors: ; Compute mV or all sensors (S8 Mode)
|
|
333 ; compute AD results in 100µV steps (16bit/sensor)
|
|
334 ; 24bit AD result is in 244,1406541nV
|
|
335 ; Devide 24bit value through 409,5999512 -> 410 (0,01% error)
|
|
336 #DEFINE ad2mv_factor .410
|
|
337 ; Sensor 1
|
|
338 clrf xC+3
|
268
|
339 movff s8_rawdata_sensor1+2,xC+2
|
|
340 movff s8_rawdata_sensor1+1,xC+1
|
|
341 movff s8_rawdata_sensor1+0,xC+0
|
113
|
342 movlw LOW ad2mv_factor
|
|
343 movwf xB+0
|
|
344 movlw HIGH ad2mv_factor
|
|
345 movwf xB+1
|
|
346 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
347 movff xC+1,o2_mv_sensor1+1
|
|
348 movff xC+0,o2_mv_sensor1+0 ; in 100uV steps
|
|
349 ; Sensor 2
|
|
350 clrf xC+3
|
268
|
351 movff s8_rawdata_sensor2+2,xC+2
|
|
352 movff s8_rawdata_sensor2+1,xC+1
|
|
353 movff s8_rawdata_sensor2+0,xC+0
|
113
|
354 movlw LOW ad2mv_factor
|
|
355 movwf xB+0
|
|
356 movlw HIGH ad2mv_factor
|
|
357 movwf xB+1
|
|
358 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
359 movff xC+1,o2_mv_sensor2+1
|
|
360 movff xC+0,o2_mv_sensor2+0 ; in 100uV steps
|
|
361 ; Sensor 3
|
|
362 clrf xC+3
|
268
|
363 movff s8_rawdata_sensor3+2,xC+2
|
|
364 movff s8_rawdata_sensor3+1,xC+1
|
|
365 movff s8_rawdata_sensor3+0,xC+0
|
113
|
366 movlw LOW ad2mv_factor
|
|
367 movwf xB+0
|
|
368 movlw HIGH ad2mv_factor
|
|
369 movwf xB+1
|
|
370 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
371 movff xC+1,o2_mv_sensor3+1
|
|
372 movff xC+0,o2_mv_sensor3+0 ; in 100uV steps
|
|
373
|
|
374 bcf new_s8_data_available ; Clear flag
|
|
375 return ; Done.
|
|
376
|
352
|
377 global transmit_setpoint ; Transmit current setpoint from WREG (in cbar) to external electronics
|
|
378 transmit_setpoint:
|
448
|
379 return
|
352
|
380 btfss s8_digital ; S8 Digital?
|
|
381 return ; No, ignore
|
|
382
|
|
383 ; Yes, transmit setpoint from WREG
|
|
384 movwf temp2 ; Store setpoint
|
|
385 clrf temp1 ; Chksum
|
|
386 movlw 0xAA ; Start Byte
|
|
387 addwf temp1,F
|
|
388 movff WREG,TXREG2
|
|
389 call rs232_wait_tx2
|
|
390
|
|
391 movlw 0x60 ; New SP
|
|
392 addwf temp1,F
|
|
393 movff WREG,TXREG2
|
|
394 call rs232_wait_tx2
|
|
395
|
|
396 movff temp2,WREG ; SP in cbar
|
|
397 addwf temp1,F
|
|
398 movff WREG,TXREG2
|
|
399 call rs232_wait_tx2
|
|
400
|
448
|
401 movff temp1,TXREG2 ; Chksum
|
352
|
402 call rs232_wait_tx2
|
|
403 return
|
113
|
404
|
|
405
|
|
406 END |