Back to Home

Capacitance Meter on ATmega8: schematic and code

Developed a capacitors capacitance meter on ATmega8 with RC charging method. Described schematics, PCB layout in EasyEDA, code with ADC and I2C LCD, 3D case. The project demonstrates the full cycle of embedded development.

ATmega8 capacitance meter: full guide from schematic to PCB
Advertisement 728x90

Building a Capacitance Meter Using ATmega8: From Schematic to Prototype

The ATmega8 microcontroller enables an accurate capacitance meter using the RC charging method. The device features an I2C LCD display, an LM7805 voltage regulator, and switchable resistors for different capacitance ranges. Development was carried out in EasyEDA for PCB design, Compass 3D for the enclosure, and Proteus for simulation.

Capacitance C is defined as C = Q/U, where charge accumulates exponentially. The time to charge to 63.2% of Ucc gives the time constant τ = R × C. The algorithm:

  • Set the discharge pin to "INPUT" to prevent discharge.
  • Record t0, the start of charging.
  • Set the charge pin to "OUTPUT" HIGH, monitor ADC until reaching 63.2% of Ucc.
  • Calculate C = (t - t0) / R.
  • Discharge through a resistor: set discharge pin to "INPUT", output to LOW.

An RC circuit with switchable resistors adjusts τ across capacitance ranges from picofarads to millifarads.

Google AdInline article slot

Schematic Design and Circuit Architecture

The ATmega8 (DIP-28) with a 10-bit ADC converts Uc into digital code. The ALU computes C based on τ. SMD 0603 resistors (1kΩ–1MΩ) form the RC network. A discharge resistor limits current. A 16×2 I2C LCD (SDA/SCL) minimizes GPIO usage. Power: 9V battery → LM7805 → 5V, filtered with 0603 ceramic and 3216 electrolytic capacitors.

AREF/AVCC tied to 5V, Vcc/GND standard. Auto-range switching via digital outputs controlling resistors.

Key Components List:

Google AdInline article slot
  • ATmega8-16PU
  • LM7805
  • I2C LCD 0x3F
  • 0603 resistors: 1k, 10k, 100k, 1M
  • Capacitors: 100nF×4, 10μF, 100μF

PCB Design in EasyEDA

PCB size: 30×38 mm. Minimum trace width b_min = I_max / (j_dop × t) = 0.254 mm (j_dop=50 A/mm², t=35 μm, I_max<0.1A). Hole diameter d=1.2 mm for leads ≤1 mm. Area S = S'/Kz, Kz=0.4.

Subtractive method: etching copper on FR4. Layout minimizes ADC signal path length to reduce noise. Ground is a solid plane; power uses wide traces. 3D view checks clearances.

PCB Parameter Calculations:

Google AdInline article slot
  • Area: S' = ∑ component area, Kz=0.3–0.6.
  • Traces: b_min based on current and manufacturing method.
  • Holes: d = d_element + |Δd| + r (r=0.1–0.4 mm).
  • Clearances: ≥0.2 mm.
  • Pads: Diameter 1.5–2×d.

Routing: analog and digital circuits separated; ground under ADC.

Enclosure and Mechanical Design

Designed in Compass 3D: battery compartment for 9V, BNC terminals for Cx, cutout for LCD, power button. Wall thickness: 2 mm, with stiffening ribs. Visualization confirms ergonomics—easy access to calibration components.

Software Implementation

C++ code for AVR-GCC. Initialize Wire and LiquidCrystal_I2C. LCD address: 0x3F. Pins: charge PB0, discharge PB1, range PB2–PB4, ADC PC0.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define LCD_ADDRESS 0x3F
#define LCD_COLS 16
#define LCD_ROWS 2
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLS, LCD_ROWS);

// Pins
const int CHARGE_PIN = 9;  // PB1
const int DISCHARGE_PIN = 10; // PB2
const int ADC_PIN = A0;   // PC0

void setup() {
  lcd.init();
  lcd.backlight();
  pinMode(CHARGE_PIN, OUTPUT);
  pinMode(DISCHARGE_PIN, OUTPUT);
  digitalWrite(CHARGE_PIN, LOW);
  digitalWrite(DISCHARGE_PIN, LOW);
  // ADC initialization
  ADMUX = (1<<REFS0); // AVCC reference
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
}

float measureCapacitance(float R) {
  // Discharge
  digitalWrite(DISCHARGE_PIN, LOW);
  delay(100);
  // Charge
  unsigned long t0 = millis();
  digitalWrite(CHARGE_PIN, HIGH);
  while (analogRead(ADC_PIN) < 645) {} // 63.2% of 1023
  unsigned long t1 = millis();
  digitalWrite(CHARGE_PIN, LOW);
  return (t1 - t0) / 1000.0 / R;
}

void loop() {
  float C = measureCapacitance(10000.0); // R=10k
  lcd.clear();
  lcd.print("C = ");
  lcd.print(C * 1e6, 1);
  lcd.print(" uF");
  delay(2000);
}

ADC polling every 10 ms, timer overflow protection. Calibration constants stored in EEPROM.

Key Takeaways

  • RC charging method achieves ±5% accuracy for C = 1nF–100μF.
  • Switching resistors extends range without sacrificing ADC resolution.
  • I2C LCD conserves GPIO pins—ideal for embedded systems.
  • The LM7805 linear regulator is simple but heats up—acceptable for prototyping.
  • Double-layer PCB with DRC checks in EasyEDA prevents routing errors.

— Editorial Team

Advertisement 728x90

Read Next