Microcontrollers Projects

Inductance and Capacitance Measurement Using PIC18 Microcontroller

When designing or debugging electronic devices, it is very important to know the values ​​of the components used on the circuit board. Most components can be easily measured and identified using a multimeter, but most common multimeters do not have the function of measuring inductance and capacitance because this is rarely needed. However, without capacitance, there is actually no circuit, and complex circuits may contain inductors. LCR (inductance-capacitance-resistance) meters can be used to determine the above components, but generally such meters are very expensive.

 Inductance and Capacitance Measurement Using PIC18 Microcontroller

In this article we will share a method that can measure inductance and capacitance with some accuracy. For this, we can use a common 8-bit microcontroller. I have used PIC18F452. Of course, any other microcontroller will be equally suitable for this purpose as long as the calculations and procedures are kept. We also need a small external analog circuit based on the LM393 dual analog comparator. This circuit is a simple Hartley oscillator . The idea is to measure the frequency or time period of the oscillator. When a new component such as an inductor is introduced to the oscillator, both its frequency and time period will change. We can then back-calculate the component values.

The PIC18F452 is an 8-bit PIC18F series microcontroller. It is much more powerful in terms of hardware than the popular PIC16F877A or PIC16F887. However, we do not need any other hardware except the capture compare module (CCP) and the timer. The main reason for using the PIC18F is that it has an operating clock speed of 40MHz.

Circuit Schematic

The following is the schematic diagram of the inductance and capacitance meter:

 Inductance and Capacitance Measurement Using PIC18 Microcontroller

Required Components

We will need all the components shown in the circuit diagram. Components L2 to L6 and C4 to C8 are test components. Rotary switches SW1 and SW2 are only used in the simulation schematic and do not exist in reality. A 2×16 alphanumeric LCD is used to display information. A push button connected to pin C0 is used for mode selection.

Code

  1. #include <18F452.h>  
  2. #device *=16  
  3. #fuses NOWDT, PUT, H4, BROWNOUT, BORV42
  4. #fuses NOLVP, NODEBUG, NOCPB, STVREN, CPD
  5. #fuses PROTECT, NOWRT, NOWRTB, NOWRTC
  6. #fuses NOWRTD, NOEBTR, NOEBTRB, NOOSCSEN
  7. #use delay(clock = 40M)   
  8. #include “lcd.c”   
  9. #define mode_button input(pin_C0)   
  10. #define C_cal_in_nF 100.0
  11. #define L_cal_in_uH 100.0              
  12. #definepi 3.142                                                     
  13. #define cal_delay 1000   
  14. #define scaling_factor_c ((10.0 / (4.0 * pi * pi * L_cal_in_uH)))   
  15. #define scaling_factor_l ((10.0 / (4.0 * pi * pi * C_cal_in_nF)))         
  16. unsigned int32 overflow_count = 0;                                                      
  17. unsigned int32 pulse_ticks = 0;                                                   
  18. unsigned int16 start_time = 0;  
  19. unsigned int16 end_time = 0;                              
  20. void setup(void);                                                                             
  21. #int_TIMER1                                                                                             
  22. void TMR_ISR(void)                 
  23. {                                                                                         
  24.     overflow_count++;      
  25. }              
  26. #int_CCP1                                                
  27. void CCP_ISR(void)
  28. {
  29.     end_time = CCP_1;                                                                                         
  30.     pulse_ticks = ((65536 * overflow_count) + end_time – start_time);
  31.     start_time = end_time;
  32.     overflow_count = 0;
  33. }
  34. void main(void)  
  35. {
  36.      short calibration_done = 0;                                                                                          
  37.      unsigned char mode = 0;        
  38.      unsigned long t = 0;      
  39.      double ref = 0.0;
  40.      double value = 0.0;
  41.      setup();                                                                              
  42.      while(TRUE)                          
  43.      {                                                                     
  44.          t = (pulse_ticks);  
  45.          value = ((double)t * (double)t);
  46.          if(mode_button == FALSE)
  47.          {
  48.             delay_ms(60);                                             
  49.             while(mode_button == FALSE);   
  50.             calibration_done = 0;
  51.             mode++;
  52.             if(mode > 1)
  53.             {
  54.                 mode = 0;
  55.             }
  56.          }  
  57.          if (calibration_done == 0)
  58.          {
  59.              lcd_putc(“\f”);               
  60.              lcd_gotoxy(1, 1);
  61.              lcd_putc(“Calibrating….”);                                                               
  62.              lcd_gotoxy(1, 2);              
  63.              lcd_putc(“Place no part.”);                                                                 
  64.              delay_ms(cal_delay);        
  65.              lcd_putc(“\f”);   
  66.              if(mode == 0)
  67.              {   
  68.                  ref = (value * scaling_factor_c);   
  69.                  lcd_gotoxy(1, 1);  
  70.                  lcd_putc(“C.ref/nF:”);         
  71.                  lcd_gotoxy(1, 2);
  72.                  printf(lcd_putc, “%3.1g “, ref);   
  73.              }
  74.              if(mode == 1)            
  75.              {                                             
  76.                  ref = (value * scaling_factor_l);
  77.                  lcd_gotoxy(1, 1);  
  78.                  lcd_putc(“L.ref/uH:”);        
  79.                  lcd_gotoxy(1, 2);
  80.                  printf(lcd_putc, “%3.1g “, ref);   
  81.              }  
  82.              delay_ms(cal_delay);        
  83.              lcd_putc(“\f”);
  84.              calibration_done = 1;
  85.          }
  86.          else
  87.          {   
  88.              lcd_gotoxy(1, 1);  
  89.              switch(mode)
  90.              {
  91.                  case 1:
  92.                  {
  93.                      value = (value * scaling_factor_c);  
  94.                      lcd_putc(“Ind./uH:”);      
  95.                      break;
  96.                  }   
  97.                  default:
  98.                  {   
  99.                      value = (value * scaling_factor_l);   
  100.                      lcd_putc(“Cap./nF:”);        
  101.                      break;
  102.                  }
  103.              }
  104.              value -= ref;
  105.              if((value < 0) || (value > 1000))            
  106.              {              
  107.                 value = 0;
  108.              }  
  109.              lcd_gotoxy(1, 2);                              
  110.              printf(lcd_putc, “%3.1g “, value);   
  111.          }
  112.          delay_ms(100);                  
  113.      };
  114. }
  115. void setup(void)                                      
  116. {                        
  117.      setup_wdt(WDT_OFF);  
  118.      setup_adc(ADC_OFF);
  119.      setup_adc_ports(NO_ANALOGS);                                                                                    
  120.      setup_spi(SPI_DISABLED);   
  121.      setup_psp(PSP_DISABLED);                  
  122.      setup_ccp1(CCP_CAPTURE_RE);
  123.      setup_ccp2(CCP_OFF);
  124.      setup_low_volt_detect(LVD_43);                                                
  125.      setup_timer_0(T0_OFF | T0_8_BIT);
  126.      setup_timer_1(T1_INTERNAL);  
  127.      setup_timer_2(T2_DISABLED, T2_DIV_BY_1, 16);
  128.      setup_timer_3(T3_DISABLED);  
  129.      set_timer0(0);
  130.      set_timer1(0);  
  131.      set_timer2(0);                                            
  132.      set_timer3(0);
  133.      enable_interrupts(INT_CCP1);      
  134.      enable_interrupts(INT_TIMER1);
  135.      enable_interrupts(global);  
  136.      lcd_init();
  137.      lcd_putc(“\f”);                              
  138. }         

Copy code

Code Description

Based on the theory discussed, we need the high processing speed of PIC18 along with the timer and capture modules. We also need an LCD to display the results. The setup() function shown below shows these modules and their settings.

  1. void setup(void)                                             
  2. {                        
  3.      setup_ccp1(CCP_CAPTURE_RE);
  4.      setup_timer_1(T1_INTERNAL);  
  5.      set_timer1(0);  
  6.      enable_interrupts(INT_CCP1);      
  7.      enable_interrupts(INT_TIMER1);
  8.      enable_interrupts(global);  
  9.      lcd_init();
  10.      lcd_putc(“\f”);      
  11. }

Copy code

The CCP1 module is set to rising edge capture. This means that CCP1 will capture the count of Timer 1 when a rising edge is detected. The CCP module in the PIC microcontroller usually works in the Timer 1 module, so its count is captured. Capturing two consecutive rising edges will result in a period measurement of the input waveform. This is what we need most.

To further make it obvious that things work in a concurrent fashion, interrupts are used. The CCP1 interrupt fires when a rising edge capture occurs, and the Timer 1 interrupt is used to keep track of timer overflows. When handling a Timer 1 overflow, the current and previous capture counts are stored. These will be used to determine the time period. Timer 1 will rarely overflow, as it will only overflow if the frequency of the input waveform is very low, which in practice will never happen.

  1. #int_TIMER1                                                                                                                              
  2. void TMR_ISR(void)                 
  3. {         
  4.     overflow_count++;      
  5. }              
  6. #int_CCP1                                                
  7. void CCP_ISR(void)
  8. {
  9.     end_time = CCP_1;                                                                                         
  10.     pulse_ticks = ((65536 * overflow_count) + end_time – start_time);
  11.     start_time = end_time;
  12.     overflow_count = 0;
  13. }

Copy code

The PLL of the PIC18 is used to up-clock the external 10MHz crystal oscillator clock to 40MHz. This is reflected in the fuse bits and clock settings.

  1. #fuses H4 ….
  2. #use delay(clock = 40M)   

Copy code

However, the PIC typically requires 4 clock cycles per instruction, so the effective system clock frequency is 10MHz.

Therefore, one tick of Timer 1 is:

Therefore, at a base frequency of 50kHz (20 µs), Timer 1 will count:

The reference inductor and capacitor values ​​can be simply known from the following equations:

The same applies to inductance measurements, and the formula simplifies to:

Fixed constants are defined in defines at the top of the code

  1. #define C_cal_in_nF 100.0
  2. #define L_cal_in_uH 100.0              
  3. #define pi 3.142                                                                                                                                             
  4. #define cal_delay 1000   
  5. #define scaling_factor_c ((10.0 / (4.0 * pi * pi * L_cal_in_uH)))   
  6. #define scaling_factor_l ((10.0 / (4.0 * pi * pi * C_cal_in_nF)))  

Copy code

Now suppose we want to measure 220nF. Therefore, for this capacitance, the oscillator frequency will be:

Timer 1 will count 355 counts while capturing this frequency from the oscillator.

Now, if we calculate back using the formula shown previously, we find that the value of the capacitor is:

Yes, the reading is a little off from the actual value, but it is close enough. The error occurs because the timer can only count to whole numbers. This error can be cleverly compensated for in the code.

The button connected to pin C0 is used to select the inductance or capacitance measurement mode. Every time the mode is changed, a calibration is required. The calibration process is simple. We just need to leave our meter unconnected to anything except the reference capacitor and inductor, as shown in the circuit diagram below. This is the Hartley oscillator, the heart of the whole device.

During this time, the reference component value is measured and saved. This value will be subtracted during the unknown component measurement. During the calibration process, the meter’s display will show instructions not to place any external components.

After calibration is completed, the unknown components can be placed and measured accordingly. These tasks are completed in the main loop function of the program.

Demo

The following is a demonstration effect of measuring capacitance and inductance values:

All documents mentioned in this article can be obtained from the following links:

https://libstock.mikroe.com/projects/view/5038/inductance-capacitance-measurement-using-pic18-microcontroller

Check Also
Close
Back to top button
error: Content is protected !!