AVR1631 - Energy Meter Reference Design with ATxmega32A4  Rev 1.0
 All Data Structures Files Functions Variables Typedefs Macros
meter_calibration.c
Go to the documentation of this file.
1 
2 /* This file has been prepared for Doxygen automatic documentation generation.*/
50 #include "meter.h"
51 
52 uint8_t rx_buffer[10] = {0},rx_complete_flag = 0,tx_count=0,rx_count = 0;
53 uint8_t tx_read[31], calibration_flag = 0, calibration_count;
54 __flash unsigned char tx_array[7][31] = {
55  {" \r\n"},
56  {"\r\nEnter the Time \r\n"},
57  {"\r\nEnter the Date \r\n"},
58  {"\r\nEnter the voltage? \r\n"},
59  {"\r\nPut the meter in No Load? \r\n"},
60  {"\r\nEnter the Watt value? \r\n"},
61  {"\r\nEnter the Current in Amps \r\n"}, };
62 
67 ISR(USARTC1_TXC_vect)
68 {
69  SLEEP.CTRL &= ~SLEEP_SEN_bm;
70  uart_print();
71 }
72 
82 ISR(USARTC1_RXC_vect)
83 {
84  SLEEP.CTRL &= ~SLEEP_SEN_bm;
85  uint8_t uart_rx = 0;
86  uart_rx = USART.DATA;
88  if ((PORTC.IN & PIN3_bm) == 0)
89  {
90  rx_complete_flag = 0x00;
91  if(uart_rx == 't')
92  {
93  calibration_flag = 1;
94  }
95  else if (uart_rx == 'v')
96  {
97  calibration_flag = 2;
98  }
99  else if (uart_rx == 'n')
100  {
101  calibration_flag = 3;
102  }
103  else if (uart_rx == 'c')
104  {
105  calibration_flag = 4;
106  }
107  else if (uart_rx == 'w')
108  {
109  calibration_flag = 5;
110  }
111  else if (uart_rx == 'i')
112  {
113  calibration_flag = 6;
114  }
115  else if(uart_rx == 13) //checks whether the received character is carriage return
116  {
117  rx_complete_flag = 1;
118  }
119  else //store the recieve character in rx_buffer
120  {
121  rx_buffer[rx_count] = uart_rx-48;
122  rx_count++;
123  }
124  // echo back the received signal
125  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
126  USART.DATA = uart_rx;
127  }
128 }
129 
133 void uart_print(void)
134 {
135  USART.DATA = tx_read[tx_count];
136  tx_count++;
137  if(tx_count > 30)
138  {
139  //disable the tx interrupt when all the data in the array is sent
140  USART.CTRLA &= ~USART_TXCINTLVL_gm;
141  tx_count = 0;
142  }
143 }
144 
149 void uart_getdata(uint8_t tx)
150 {
151  //load the array to be printed in hyperterminal
152  read_tx_array(tx);
153  //clear the receive buffer
154  rx_count = 0;
155  for(uint8_t k = 0; k < 9; k++)
156  rx_buffer[k] = 0;
157  //enable transmit interrupt
158  USART.CTRLA |= USART_TXCINTLVL0_bm;
159  uart_print();
160  while(rx_complete_flag == 0){__watchdog_reset();}
161  rx_complete_flag = 0;
162  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
163  USART.DATA = 10;
164  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
165  USART.DATA = 13;
166 }
167 
172 void read_tx_array(uint8_t cnt)
173 {
174  for(uint8_t k = 0; k < 30; k++)
175  {
176  tx_read[k] = tx_array[cnt][k];
177  }
178 }
179 
184 {
185  uart_getdata(2);
186  calibrate_date();
187  uart_getdata(1);
188  calibrate_time();
189  calibration_flag = 0;
190 }
191 
195 void calibrate_time(void)
196 {
197  rtcTime.hr = rx_buffer[0]*10+rx_buffer[1];
198  rtcTime.min = rx_buffer[3]*10+rx_buffer[4];
199  rtcTime.sec = rx_buffer[6]*10+rx_buffer[7];
200  key_flag = 0;
201 }
202 
206 void calibrate_date(void)
207 {
208  rtcTime.day = rx_buffer[0]*10+rx_buffer[1];
209  rtcTime.month = rx_buffer[3]*10+rx_buffer[4];
210  rtcTime.year = rx_buffer[6]*1000+rx_buffer[7]*100+rx_buffer[8]*10+rx_buffer[9];
211 }
212 
213 
221 {
222  static float calibration_temp = 0;
223  static int64_t calibration_watt = 0;
224  if (calibration_count < 1)
225  {
226  uart_getdata(4);
227  calibration_temp = 0;
228  if(rx_buffer[0] != 0x49)
229  {
230  calibration_flag = 0;
231  calibration_count = 0xFF;
232  }
233  meter.shunt_offset[6] = 0;
234  meter.watt_offset[6] = 0;
235  gain_stage = 6;
236  offset_cnt = 6;
237  }
238  else
239  {
240  calibration_temp = calibration_temp + (float)shunt_temp;
241  calibration_watt = calibration_watt + (int64_t)watts_sum_calib;
242  }
243  calibration_count++;
244  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
245  USART.DATA = '.';
246  if (calibration_count == 30)
247  {
248  calibration_temp /= calibration_count;
249  meter.shunt_offset[6] = (uint16_t)calibration_temp;
250  eeprom.shunt_offset[6] = meter.shunt_offset[6];
251  calibration_watt /= (calibration_count);
252  meter.watt_offset[6] = -1*(int32_t)calibration_watt;
253  eeprom.watt_offset[6] = meter.watt_offset[6];
254  calibration_watt = 0;
255  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
256  USART.DATA = 10;
257  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
258  USART.DATA = 13;
259  calibration_temp = 0;
260  calibration_flag = 0;
261  calibration_count = 0;
262  }
263 }
264 
272 {
273  static float calibration_temp = 0, volt_input = 0;
274 
275  if (calibration_count < 1)
276  {
277  //uart_getdata((unsigned char *)&tx_array[3][0]);
278  uart_getdata(3);
279  calibration_temp = 0;
280  volt_input = (float) (rx_buffer[0]*100 + rx_buffer[1]*10 + rx_buffer[2]);
281  volt_input += (float) rx_buffer[4]/10 + (float)rx_buffer[5]/100;
282  }
283  calibration_count++;
284  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
285  USART.DATA = '.';
286  calibration_temp = calibration_temp + (float)volt_temp;
287  if (calibration_count > 30)
288  {
289  calibration_temp /= calibration_count;
290  meter.volt_const = (uint16_t)(65536* (volt_input/sqrt(calibration_temp)));
291  eeprom.volt_const = meter.volt_const;
292  calibration_temp = 0;
293  calibration_flag = 0;
294  calibration_count = 0;
295  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
296  USART.DATA = 10;
297  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
298  USART.DATA = 13;
299  }
300 
301 }
302 
310 {
311  float calib_temp;
312  static float calibration_temp = 0, current_input = 0;
313  static uint8_t cal_gain_stage = 0, cal_offset_cnt = 0;
314  if (calibration_count < 1)
315  {
316  uart_getdata(6);
317  calibration_temp = 0;
318  calib_temp = (float)(rx_buffer[0]*10 + rx_buffer[1]);
319  calib_temp += (float)rx_buffer[3]/10 + (float)rx_buffer[4]/100 + (float)rx_buffer[5]/1000;
320  current_input = calib_temp;
321  key_flag = 3;
322  if(current_input < 0.500)
323  {
324  cal_gain_stage =6;
325  cal_offset_cnt = 6;
326  }
327  else if(current_input > 0.500 && current_input < 1.500)
328  {
329  cal_gain_stage = 5;
330  cal_offset_cnt = 6;
331  }
332  else if(current_input > 1.500 && current_input < 2.500)
333  {
334  cal_gain_stage = 4;
335  cal_offset_cnt = 6;
336  }
337  else if(current_input > 2.500 && current_input < 4.000)
338  {
339  cal_gain_stage = 3;
340  cal_offset_cnt = 6;
341  }
342  else if(current_input > 4.000 && current_input < 7.000)
343  {
344  cal_gain_stage = 2;
345  cal_offset_cnt = 6;
346  }
347  else if(current_input > 7.000 && current_input < 14.500)
348  {
349  cal_gain_stage = 1;
350  cal_offset_cnt = 6;
351  }
352  else if(current_input > 14.500)
353  {
354  cal_gain_stage = 0;
355  cal_offset_cnt = 5;
356  }
357  else
358  {
359  calibration_flag = 0;
360  calibration_count = 0xFF;
361  }
362  }
363  else
364  {
365  calibration_temp = calibration_temp + (float)shunt_temp;
366  }
367  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
368  USART.DATA = '.';
369  calibration_count++;
370  gain_stage = cal_gain_stage;
371  offset_cnt = cal_offset_cnt;
372  if(cal_offset_cnt == 6 && offset_cnt!= 6)
373  {
375  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
376  ADC_CH_GAIN_64X_gc);
377  }
378  else if(cal_offset_cnt ==5 && offset_cnt!= 5)
379  {
381  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
382  ADC_CH_GAIN_32X_gc);
383  }
384  if (calibration_count > 30)
385  {
386  calibration_temp /= (calibration_count-1);
387  meter.shunt_const[cal_gain_stage] = (uint16_t)(65536*(current_input/sqrt(calibration_temp)));
388  eeprom.shunt_const[cal_gain_stage] = meter.shunt_const[cal_gain_stage];
389  calibration_temp = 0;
390  calibration_flag = 0;
391  calibration_count = 0;
392  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
393  USART.DATA = 10;
394  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
395  USART.DATA = 13;
396  }
397 }
398 
405 void calibrate_watt(void)
406 {
407  static int64_t calibration_watt = 0;
408  static uint8_t cal_gain_stage = 0, cal_offset_cnt = 0;
409  static uint16_t watt_input = 0;
410  static float A1_temp, B1_temp;
411  if (calibration_count < 1)
412  {
413  uart_getdata(5);
414  calibration_watt = 0;
415  watt_input = rx_buffer[0]*1000 + rx_buffer[1]*100 + rx_buffer[2]*10 + rx_buffer[3];
416  key_flag = 4;
417  if(Irms[0] < 500)
418  {
419  cal_gain_stage =6;
420  cal_offset_cnt = 6;
421  }
422  else if(Irms[0] > 500 && Irms[0] < 1500)
423  {
424  cal_gain_stage = 5;
425  cal_offset_cnt = 6;
426  }
427  else if(Irms[0] > 1500 && Irms[0] < 2500)
428  {
429  cal_gain_stage = 4;
430  cal_offset_cnt = 6;
431  }
432  else if(Irms[0] > 2500 && Irms[0] < 4000)
433  {
434  cal_gain_stage = 3;
435  cal_offset_cnt = 6;
436  }
437  else if(Irms[0] > 4000 && Irms[0] < 7000)
438  {
439  cal_gain_stage = 2;
440  cal_offset_cnt = 6;
441  }
442  else if(Irms[0] > 7000 && Irms[0] < 14500)
443  {
444  cal_gain_stage = 1;
445  cal_offset_cnt = 6;
446  }
447  else if(Irms[0] > 14500)
448  {
449  cal_gain_stage = 0;
450  cal_offset_cnt = 5;
451  }
452  else
453  {
454  calibration_flag = 0;
455  calibration_count = 0xFF;
456  }
457  A1_temp = meter.A1[cal_gain_stage];
458  B1_temp = meter.B1[cal_gain_stage];
459  meter.A1[cal_gain_stage] = 1;
460  meter.B1[cal_gain_stage] = 0;
461  }
462  else
463  {
464  calibration_watt = calibration_watt + (int64_t)active_energy_signed;
465  }
466  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
467  USART.DATA = '.';
468  calibration_count++;
469  if(cal_offset_cnt == 6 && offset_cnt!= 6)
470  {
472  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
473  ADC_CH_GAIN_64X_gc);
474  }
475  else if(cal_offset_cnt ==5 && offset_cnt!= 5)
476  {
478  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
479  ADC_CH_GAIN_32X_gc);
480  }
481  if (calibration_count > 30)
482  {
483  calibration_watt /= (calibration_count-1);
484  meter.watt_const[cal_gain_stage] = (float)watt_input/abs(calibration_watt);
485  eeprom.watt_const[cal_gain_stage] = meter.watt_const[cal_gain_stage];
486  meter.A1[cal_gain_stage] = A1_temp;
487  meter.B1[cal_gain_stage] = B1_temp;
488  calibration_watt = 0;
489  calibration_flag = 0;
490  calibration_count = 0;
491  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
492  USART.DATA = 10;
493  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
494  USART.DATA = 13;
495  }
496 }
497 
505 void calibrate_phase(void)
506 {
507  float calib_temp;
508  static float calibration_temp = 0, current_input = 0;
509  float pf_temp;
510  static uint8_t cal_gain_stage = 0, cal_offset_cnt = 0;
511  if (calibration_count < 1)
512  {
513  //uart_getdata((unsigned char *)&tx_array[6][0]);
514  uart_getdata(6);
515  calibration_temp = 0;
516  calib_temp = (float)(rx_buffer[0]*10 + rx_buffer[1]);
517  calib_temp += (float)rx_buffer[3]/10 + (float)rx_buffer[4]/100 + (float)rx_buffer[5]/1000;
518  current_input = calib_temp;
519  key_flag = 6;
520  if(current_input > 0.001 && current_input < 0.500)
521  {
522  cal_gain_stage =6;
523  cal_offset_cnt = 6;
524  }
525  else if(current_input > 0.500 && current_input < 1.500)
526  {
527  cal_gain_stage = 5;
528  cal_offset_cnt = 6;
529  }
530  else if(current_input > 1.500 && current_input < 2.500)
531  {
532  cal_gain_stage = 4;
533  cal_offset_cnt = 6;
534  }
535  else if(current_input > 2.500 && current_input < 4.000)
536  {
537  cal_gain_stage = 3;
538  cal_offset_cnt = 6;
539  }
540  else if(current_input > 4.000 && current_input < 7.000)
541  {
542  cal_gain_stage = 2;
543  cal_offset_cnt = 6;
544  }
545  else if(current_input > 7.000 && current_input < 14.500)
546  {
547  cal_gain_stage = 1;
548  cal_offset_cnt = 6;
549  }
550  else if(current_input > 14.500)
551  {
552  cal_gain_stage = 0;
553  cal_offset_cnt = 5;
554  }
555  else
556  {
557  calibration_flag = 0;
558  calibration_count = 0xFF;
559  }
560  meter.A1[cal_gain_stage] = 1;
561  meter.B1[cal_gain_stage] = 0;
562  }
563  else
564  {
565  calibration_temp = calibration_temp + ((float)active_power[0]);
566  }
567  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
568  USART.DATA = '.';
569  calibration_count++;
570  gain_stage = cal_gain_stage;
571  offset_cnt = cal_offset_cnt;
572  key_flag = 6;
573  if (calibration_count > 60)
574  {
575  calibration_temp /= (calibration_count-1);
576  pf_temp = calibration_temp / (float)(240 * current_input);
577  phase_calc(pf_temp, cal_gain_stage);
578  calibration_temp = 0;
579  calibration_flag = 0;
580  calibration_count = 0;
581  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
582  USART.DATA = 10;
583  while(USART.STATUS & USART_TXCIF_bm == 0 ){}
584  USART.DATA = 13;
585  }
586 
587 }
588 
592 void phase_calc(float pf_avg, uint8_t g_stage)
593 {
594  float phase_angle, g_delay, t1, t2, t3, beta, gain;
595  phase_angle = acos(pf_avg) - acos(0.5);
596  g_delay = phase_angle/OMEGA;
597 
598  t1 = (1-(2*g_delay)) *cos(OMEGA);
599  t2= sqrt( pow((1-(2*g_delay)),2) * (cos(OMEGA)*cos(OMEGA)) + 4*g_delay*(1-g_delay));
600  t3 = 2*(1-g_delay);
601  beta = -(t1-t2)/t3;
602  eeprom.B1[g_stage] = beta;
603  meter.B1[g_stage] = beta;
604  gain = pow(pow( (cos(OMEGA) + beta),2) + pow(sin(OMEGA),2),-0.5);
605  eeprom.A1[g_stage] = gain;
606  meter.A1[g_stage] = gain;
607 }
608 
609