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
|
|
10 #include "ostc3.inc"
|
|
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
|
|
18 global calibrate_mix
|
|
19 calibrate_mix:
|
|
20 ; calibrate S8 HUD
|
|
21 btfss s8_digital ; S8 Digital?
|
|
22 bra calibrate_mix2 ; No
|
|
23
|
|
24 clrf temp1 ; Chksum
|
|
25 movlw 0xAA ; Start Byte
|
|
26 addwf temp1,F
|
|
27 movff WREG,TXREG2
|
|
28 call rs232_wait_tx2
|
|
29
|
|
30 movlw 0x31 ; Calibrate
|
|
31 addwf temp1,F
|
|
32 movff WREG,TXREG2
|
|
33 call rs232_wait_tx2
|
|
34
|
|
35 movff opt_calibration_O2_ratio,WREG ; Calibration gas %O2
|
|
36 addwf temp1,F
|
|
37 movff WREG,TXREG2
|
|
38 call rs232_wait_tx2
|
|
39
|
|
40 movff amb_pressure+0,WREG ; Ambient pressure
|
|
41 addwf temp1,F
|
|
42 movff WREG,TXREG2
|
|
43 call rs232_wait_tx2
|
|
44 movff amb_pressure+1,WREG
|
|
45 addwf temp1,F
|
|
46 movff WREG,TXREG2
|
|
47 call rs232_wait_tx2
|
|
48
|
|
49 movff temp1,TXREG2 ; Chksum
|
|
50 call rs232_wait_tx2
|
|
51
|
|
52 calibrate_mix2:
|
|
53 movff opt_calibration_O2_ratio,WREG ; Calibration gas %O2
|
|
54 mullw .100
|
|
55 movff PRODL,xA+0
|
|
56 movff PRODH,xA+1
|
|
57 ; (%O2*100)*[ambient,mbar]/100 -> xC
|
|
58 movff amb_pressure+0,xB+0
|
|
59 movff amb_pressure+1,xB+1
|
|
60 call mult16x16 ;xA*xB=xC
|
|
61 movlw LOW .100
|
|
62 movwf xB+0
|
|
63 movlw HIGH .100
|
|
64 movwf xB+1
|
|
65 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
66 movff o2_mv_sensor1+0,xB+0
|
|
67 movff o2_mv_sensor1+1,xB+1
|
|
68 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
69 ; xC= ppO2/mV
|
|
70 movff xC+0,opt_x_s1+0
|
|
71 movff xC+1,opt_x_s1+1 ; Factor for Sensor1
|
|
72
|
|
73 movff opt_calibration_O2_ratio,WREG ; Calibration gas %O2
|
|
74 mullw .100
|
|
75 movff PRODL,xA+0
|
|
76 movff PRODH,xA+1
|
|
77 ; (%O2*100)*[ambient,mbar]/100 -> xC
|
|
78 movff amb_pressure+0,xB+0
|
|
79 movff amb_pressure+1,xB+1
|
|
80 call mult16x16 ;xA*xB=xC
|
|
81 movlw LOW .100
|
|
82 movwf xB+0
|
|
83 movlw HIGH .100
|
|
84 movwf xB+1
|
|
85 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
86 movff o2_mv_sensor2+0,xB+0
|
|
87 movff o2_mv_sensor2+1,xB+1
|
|
88 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
89 ; xC= ppO2/mV
|
|
90 movff xC+0,opt_x_s2+0
|
|
91 movff xC+1,opt_x_s2+1 ; Factor for Sensor2
|
|
92
|
|
93 movff opt_calibration_O2_ratio,WREG ; Calibration gas %O2
|
|
94 mullw .100
|
|
95 movff PRODL,xA+0
|
|
96 movff PRODH,xA+1
|
|
97 ; (%O2*100)*[ambient,mbar]/100 -> xC
|
|
98 movff amb_pressure+0,xB+0
|
|
99 movff amb_pressure+1,xB+1
|
|
100 call mult16x16 ;xA*xB=xC
|
|
101 movlw LOW .100
|
|
102 movwf xB+0
|
|
103 movlw HIGH .100
|
|
104 movwf xB+1
|
|
105 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
106 movff o2_mv_sensor3+0,xB+0
|
|
107 movff o2_mv_sensor3+1,xB+1
|
|
108 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
109 ; xC= ppO2/mV
|
|
110 movff xC+0,opt_x_s3+0
|
|
111 movff xC+1,opt_x_s3+1 ; Factor for Sensor3
|
|
112
|
|
113 ; Result is in 100µV
|
|
114 movff o2_mv_sensor1+0, sub_a+0
|
|
115 movff o2_mv_sensor1+1, sub_a+1
|
|
116 movlw LOW min_mv
|
|
117 movwf sub_b+0
|
|
118 movlw HIGH min_mv
|
|
119 movwf sub_b+1
|
|
120 call sub16 ; sub_c = sub_a - sub_b
|
|
121 bsf sensor1_active ; Sensor active!
|
|
122 btfsc neg_flag
|
|
123 bcf sensor1_active
|
|
124
|
|
125 ; Result is in 100µV
|
|
126 movff o2_mv_sensor2+0, sub_a+0
|
|
127 movff o2_mv_sensor2+1, sub_a+1
|
|
128 movlw LOW min_mv
|
|
129 movwf sub_b+0
|
|
130 movlw HIGH min_mv
|
|
131 movwf sub_b+1
|
|
132 call sub16 ; sub_c = sub_a - sub_b
|
|
133 bsf sensor2_active ; Sensor active!
|
|
134 btfsc neg_flag
|
|
135 bcf sensor2_active
|
|
136
|
|
137 ; Result is in 100µV
|
|
138 movff o2_mv_sensor3+0, sub_a+0
|
|
139 movff o2_mv_sensor3+1, sub_a+1
|
|
140 movlw LOW min_mv
|
|
141 movwf sub_b+0
|
|
142 movlw HIGH min_mv
|
|
143 movwf sub_b+1
|
|
144 call sub16 ; sub_c = sub_a - sub_b
|
|
145 bsf sensor3_active ; Sensor active!
|
|
146 btfsc neg_flag
|
|
147 bcf sensor3_active
|
|
148
|
|
149 ; When no sensor is found, enable all three to show error state
|
|
150 btfsc sensor1_active
|
|
151 return
|
|
152 btfsc sensor2_active
|
|
153 return
|
|
154 btfsc sensor3_active
|
|
155 return
|
|
156 bsf sensor1_active
|
|
157 bsf sensor2_active
|
|
158 bsf sensor3_active
|
|
159 ; Clear factors
|
|
160 banksel opt_x_s1+0
|
|
161 clrf opt_x_s1+0
|
|
162 clrf opt_x_s1+1
|
|
163 clrf opt_x_s2+0
|
|
164 clrf opt_x_s2+1
|
|
165 clrf opt_x_s3+0
|
|
166 clrf opt_x_s3+1
|
|
167 banksel common
|
|
168 return
|
|
169
|
|
170 compute_ppo2_analog:
|
|
171 call get_analog_inputs
|
|
172 bra compute_ppo2_common
|
|
173
|
|
174 global compute_ppo2 ; compute mv_sensorX and ppo2_sensorX arrays
|
|
175 compute_ppo2:
|
|
176 btfss c3_hardware ; C3 hardware?
|
|
177 return ; No
|
|
178
|
|
179 btfss s8_digital ; =1: Digital I/O
|
|
180 bra compute_ppo2_analog ; use analog
|
|
181
|
|
182 ; use digital
|
|
183 btfss new_s8_data_available ; =1: New data frame recieved
|
|
184 return
|
|
185 call compute_mvolts_for_all_sensors
|
|
186
|
|
187 compute_ppo2_common:
|
|
188 ; o2_mv_sensor1:2 * opt_x_s1:2 = o2_ppo2_sensor1/10000
|
|
189 movff o2_mv_sensor1+0,xA+0
|
|
190 movff o2_mv_sensor1+1,xA+1
|
|
191 movff opt_x_s1+0,xB+0
|
|
192 movff opt_x_s1+1,xB+1
|
|
193 call mult16x16 ;xA:2*xB:2=xC:4
|
|
194 movlw LOW .1000
|
|
195 movwf xB+0
|
|
196 movlw HIGH .1000
|
|
197 movwf xB+1
|
|
198 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
199 movlw d'1'
|
|
200 addwf xC+0,F
|
|
201 movlw d'0'
|
|
202 addwfc xC+1,F
|
|
203 movff xC+0,o2_ppo2_sensor1+0
|
|
204 movff xC+1,o2_ppo2_sensor1+1 ; result in 0.01bar
|
|
205 ; Set to zero if sensor is not active!
|
|
206 btfss sensor1_active
|
|
207 clrf o2_ppo2_sensor1+0
|
|
208 btfss sensor1_active
|
|
209 clrf o2_ppo2_sensor1+1
|
|
210
|
|
211 ; o2_mv_sensor2:2 * opt_x_s1:2 = o2_ppo2_sensor2/10000
|
|
212 movff o2_mv_sensor2+0,xA+0
|
|
213 movff o2_mv_sensor2+1,xA+1
|
|
214 movff opt_x_s2+0,xB+0
|
|
215 movff opt_x_s2+1,xB+1
|
|
216 call mult16x16 ;xA:2*xB:2=xC:4
|
|
217 movlw LOW .1000
|
|
218 movwf xB+0
|
|
219 movlw HIGH .1000
|
|
220 movwf xB+1
|
|
221 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
222 movlw d'1'
|
|
223 addwf xC+0,F
|
|
224 movlw d'0'
|
|
225 addwfc xC+1,F
|
|
226 movff xC+0,o2_ppo2_sensor2+0
|
|
227 movff xC+1,o2_ppo2_sensor2+1 ; result in 0.01bar
|
|
228 ; Set to zero if sensor is not active!
|
|
229 btfss sensor2_active
|
|
230 clrf o2_ppo2_sensor2+0
|
|
231 btfss sensor2_active
|
|
232 clrf o2_ppo2_sensor2+1
|
|
233
|
|
234 ; o2_mv_sensor3:2 * opt_x_s1:2 = o2_ppo2_sensor3/10000
|
|
235 movff o2_mv_sensor3+0,xA+0
|
|
236 movff o2_mv_sensor3+1,xA+1
|
|
237 movff opt_x_s3+0,xB+0
|
|
238 movff opt_x_s3+1,xB+1
|
|
239 call mult16x16 ;xA:2*xB:2=xC:4
|
|
240 movlw LOW .1000
|
|
241 movwf xB+0
|
|
242 movlw HIGH .1000
|
|
243 movwf xB+1
|
|
244 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
245 movlw d'1'
|
|
246 addwf xC+0,F
|
|
247 movlw d'0'
|
|
248 addwfc xC+1,F
|
|
249 movff xC+0,o2_ppo2_sensor3+0
|
|
250 movff xC+1,o2_ppo2_sensor3+1 ; result in 0.01bar
|
|
251 ; Set to zero if sensor is not active!
|
|
252 btfss sensor3_active
|
|
253 clrf o2_ppo2_sensor3+0
|
|
254 btfss sensor3_active
|
|
255 clrf o2_ppo2_sensor3+1
|
|
256
|
|
257 return ; Done.
|
|
258
|
|
259
|
|
260 compute_mvolts_for_all_sensors: ; Compute mV or all sensors (S8 Mode)
|
|
261 ; compute AD results in 100µV steps (16bit/sensor)
|
|
262 ; 24bit AD result is in 244,1406541nV
|
|
263 ; Devide 24bit value through 409,5999512 -> 410 (0,01% error)
|
|
264 #DEFINE ad2mv_factor .410
|
|
265 ; Sensor 1
|
|
266 clrf xC+3
|
|
267 movff ir_buffer+.6,xC+2
|
|
268 movff ir_buffer+.5,xC+1
|
|
269 movff ir_buffer+.4,xC+0
|
|
270 movlw LOW ad2mv_factor
|
|
271 movwf xB+0
|
|
272 movlw HIGH ad2mv_factor
|
|
273 movwf xB+1
|
|
274 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
275 movff xC+1,o2_mv_sensor1+1
|
|
276 movff xC+0,o2_mv_sensor1+0 ; in 100uV steps
|
|
277 ; Sensor 2
|
|
278 clrf xC+3
|
|
279 movff ir_buffer+.9,xC+2
|
|
280 movff ir_buffer+.8,xC+1
|
|
281 movff ir_buffer+.7,xC+0
|
|
282 movlw LOW ad2mv_factor
|
|
283 movwf xB+0
|
|
284 movlw HIGH ad2mv_factor
|
|
285 movwf xB+1
|
|
286 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
287 movff xC+1,o2_mv_sensor2+1
|
|
288 movff xC+0,o2_mv_sensor2+0 ; in 100uV steps
|
|
289 ; Sensor 3
|
|
290 clrf xC+3
|
|
291 movff ir_buffer+.12,xC+2
|
|
292 movff ir_buffer+.11,xC+1
|
|
293 movff ir_buffer+.10,xC+0
|
|
294 movlw LOW ad2mv_factor
|
|
295 movwf xB+0
|
|
296 movlw HIGH ad2mv_factor
|
|
297 movwf xB+1
|
|
298 call div32x16 ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder
|
|
299 movff xC+1,o2_mv_sensor3+1
|
|
300 movff xC+0,o2_mv_sensor3+0 ; in 100uV steps
|
|
301
|
|
302 bcf new_s8_data_available ; Clear flag
|
|
303 return ; Done.
|
|
304
|
|
305
|
|
306
|
|
307 END |