Простой измеритель Емкости КОНДЕНСАТОРА на Arduino Nano и OLED Дисплее

Что для этого нам понадобятся:

  1. Arduino Nano (или любой другой совместимый Arduino).
  2. OLED-дисплей 128×64 (обычно на контроллере SSD1306, подключается по I2C).
  3. Конденсатор, ёмкость которого будем измерять.
  4. Резистор известного номинала (например, 10 кОм или 100 кОм) для формирования RC-цепочки.

Принцип измерения ёмкости (RC-метод):

Мы будем использовать метод зарядки/разрядки конденсатора через резистор. Время зарядки (или разрядки) конденсатора в RC-цепи пропорционально его ёмкости и сопротивлению резистора.

  • RC-постоянная времени (τ): Это время, за которое конденсатор зарядится примерно до 63.2% от приложенного напряжения или разрядится до 36.8% от начального напряжения. Формула: tau=RtimesC (где tau в секундах, R в Омах, C в Фарадах).
  • Мы будем измерять время, за которое аналоговый вход Arduino достигает определённого порогового значения при зарядке конденсатора.

Схема подключения:

  • OLED-дисплей:
    • VCC -> Arduino 5V
    • GND -> Arduino GND
    • SDA -> Arduino A4 (для I2C)
    • SCL -> Arduino A5 (для I2C)
  • Конденсатор и Резистор (RC-цепь):
    • Arduino Digital Pin 2 (или другой цифровой пин) -> Один конец Резистора (R)
    • Другой конец Резистора (R) -> Один конец Конденсатора (C)
    • Другой конец Конденсатора (C) -> Arduino GND
    • Точка соединения Резистора (R) и Конденсатора (C) -> Arduino Analog Pin A0 (для измерения напряжения)
    Важно: Для измерения ёмкости, конденсатор должен быть полностью разряжен перед каждым измерением. Программа будет это делать автоматически.

Необходимые библиотеки:

Вам понадобятся две библиотеки для работы с OLED-дисплеем SSD1306:

  1. Adafruit GFX Library (базовая графическая библиотека)
  2. Adafruit SSD1306 (драйвер для конкретного дисплея)

Их можно установить через «Менеджер библиотек» (Sketch -> Include Library -> Manage Libraries…) в Arduino IDE.

Программа для Arduino Nano:

#include <Wire.h>           // Для связи по I2C (для OLED-дисплея)
#include <Adafruit_GFX.h>   // Базовая графическая библиотека
#include <Adafruit_SSD1306.h> // Драйвер для SSD1306 OLED-дисплея

// Определяем размеры OLED-дисплея
#define SCREEN_WIDTH 128    // Ширина в пикселях
#define SCREEN_HEIGHT 64    // Высота в пикселях

// Объект дисплея (создаем экземпляр SSD1306)
// Параметры: (Ширина, Высота, &Wire - объект I2C, Reset-пин дисплея - обычно не используется для I2C, поэтому -1)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// ---------- Пины для измерения конденсатора ----------
const int chargePin = 2;    // Цифровой пин для зарядки/разрядки конденсатора
const int analogPin = A0;   // Аналоговый пин для измерения напряжения на конденсаторе

// ---------- Параметры измерения ----------
const float R_VALUE_KOHM = 100.0; // Номинал резистора в кОм (например, 100 кОм)
                                  // Чем больше резистор, тем дольше зарядка для больших ёмкостей
                                  // Чем меньше резистор, тем быстрее зарядка для малых ёмкостей

const int VOLTAGE_THRESHOLD = 648; // Пороговое значение АЦП для измерения (примерно 63.2% от 1023, если питание 5В)
                                   // 5В * 0.632 = 3.16В. Для 10-битного АЦП (0-1023), 3.16В/5В * 1023 = 646.6. Округлим до 647-648.
                                   // Вы можете настроить этот порог для лучшей точности.

// ---------- Переменные для измерения ----------
unsigned long startTime;
unsigned long endTime;
float capacitance_uF; // Измеренная ёмкость в микрофарадах

void setup() {
  Serial.begin(9600); // Инициализация последовательного порта для отладки

  // Инициализация OLED-дисплея по адресу I2C 0x3C (или 0x3D).
  // Проверьте адрес вашего дисплея, если он не работает.
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("Ошибка инициализации SSD1306!"));
    for (;;) ; // Бесконечный цикл, если дисплей не найден
  }

  // Очистка буфера дисплея
  display.clearDisplay();
  display.setTextSize(1);      // Размер текста (1x)
  display.setTextColor(SSD1306_WHITE); // Цвет текста
  display.setCursor(0, 0);     // Установка курсора в начало
  display.println("Измерение емкости...");
  display.display();           // Вывод на дисплей
  delay(2000);
}

void loop() {
  // 1. Разрядка конденсатора:
  pinMode(chargePin, OUTPUT);    // Устанавливаем пин chargePin как выход
  digitalWrite(chargePin, LOW);  // Подключаем конденсатор к земле через chargePin для разрядки
  delay(10); // Ждем короткое время для полной разрядки

  // 2. Настройка пинов для измерения:
  pinMode(chargePin, INPUT);     // Отключаем chargePin (переводим в высокоимпедансное состояние)
  // Это позволит пину "плавать" и заряжаться через резистор.
  // Можно также установить его как INPUT_PULLUP, но для нашего метода лучше INPUT.

  // 3. Запуск зарядки и измерение времени:
  startTime = micros();          // Запоминаем текущее время в микросекундах
  
  // Читаем аналоговый вход, пока напряжение не достигнет порога
  while (analogRead(analogPin) < VOLTAGE_THRESHOLD) {
    // Ждем, пока конденсатор зарядится
    // Можно добавить небольшой delay(1) или yield() для предотвращения зависания
    // при очень больших ёмкостях, если loop() должен выполнять другие задачи
  }
  endTime = micros();            // Запоминаем время, когда порог достигнут

  // 4. Расчет ёмкости:
  // Формула для RC-постоянной: tau = R * C
  // Время зарядки до 63.2% (или нашего порога) = RC
  // C = время / R
  // C (Фарад) = (endTime - startTime) (сек) / R (Ом)
  // Мы используем микросекунды и килоомы, поэтому:
  // C (мкФ) = (endTime - startTime) (мкс) / (R_VALUE_KOHM * 1000 Ом/кОм)
  //           = (endTime - startTime) / R_VALUE_KOHM / 1000
  //           = (время_в_микросекундах / 1000) / R_VALUE_KOHM (что даст нФ)
  // C (мкФ) = (время_в_микросекундах / 1000.0) / R_VALUE_KOHM (мкФ) * 1000 (нФ в мкФ)
  // C (мкФ) = (время_в_микросекундах / 1000.0) / R_VALUE_KOHM

  // Если R_VALUE_KOHM в кОм, а время в мкс, то C будет в нанофарадах (нФ).
  // 1 нФ = 0.001 мкФ
  // C (мкФ) = (время_в_мкс / 1000) / (R_VALUE_KOHM * 1000) (мкФ)
  // Более точно: C (F) = delta_t (s) / R (Ohm)
  // C (uF) = (delta_t (us) / 1,000,000) / (R_VALUE_KOHM * 1000) * 1,000,000
  // C (uF) = delta_t (us) / (R_VALUE_KOHM * 1000)
  
  // Более простая формула для uF:
  // C (uF) = (endTime - startTime) / R_VALUE_KOHM; // Где время в микросекундах, R в килоомах.
  // Это приближенная формула, работает хорошо для 63.2% зарядки.
  // Если время в микросекундах (us), а R_VALUE_KOHM в кОм, то ёмкость будет в нФ.
  // Для мкФ:
  capacitance_uF = (float)(endTime - startTime) / R_VALUE_KOHM; // Это даст ёмкость в нанофарадах (нФ)
                                                                 // (us / kOhm = nF)

  // Переводим нФ в мкФ для более удобного отображения, если ёмкость большая
  if (capacitance_uF >= 1000.0) { // Если ёмкость 1000 нФ и больше
      capacitance_uF /= 1000.0; // Делим на 1000 для получения мкФ
      Serial.print("Емкость: ");
      Serial.print(capacitance_uF, 2); // 2 знака после запятой
      Serial.println(" мкФ");

      // Вывод на OLED
      display.clearDisplay();
      display.setTextSize(2); // Крупнее текст для значения
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 0);
      display.print(capacitance_uF, 2); // Выводим значение
      display.println(" uF");
      display.setTextSize(1);
      display.println(); // Пустая строка
      display.println("  (microFarad)");
      display.display();
  } else {
      Serial.print("Емкость: ");
      Serial.print(capacitance_uF, 2);
      Serial.println(" нФ");

      // Вывод на OLED
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(SSD1306_WHITE);
      display.setCursor(0, 0);
      display.print(capacitance_uF, 2);
      display.println(" nF");
      display.setTextSize(1);
      display.println(); // Пустая строка
      display.println("  (nanoFarad)");
      display.display();
  }

  delay(1000); // Задержка 1 секунда перед следующим измерением
}

Пояснения к коду:

  1. Подключение библиотек: Wire.h для I2C-связи, Adafruit_GFX.h и Adafruit_SSD1306.h для работы с OLED-дисплеем.
  2. Настройка OLED:
    • #define SCREEN_WIDTH 128 и #define SCREEN_HEIGHT 64: Определяют разрешение дисплея.
    • Adafruit_SSD1306 display(...): Создает объект для работы с дисплеем. Адрес 0x3C (или 0x3D) — стандартный для многих SSD1306. Если дисплей не работает, проверьте его I2C-адрес.
  3. Пины для измерения:
    • chargePin (пин 2): Используется для управления зарядкой/разрядкой конденсатора.
    • analogPin (пин A0): Аналоговый вход для измерения напряжения на конденсаторе.
  4. R_VALUE_KOHM:ОЧЕНЬ ВАЖНО! Укажите здесь точный номинал вашего резистора в килоомах (кОм). Чем точнее вы измерите этот резистор мультиметром, тем точнее будут измерения ёмкости.
    • Для ёмкостей в диапазоне нФ используйте резистор 100 кОм — 1 МОм.
    • Для ёмкостей в диапазоне мкФ используйте резистор 10 кОм — 100 кОм.
  5. VOLTAGE_THRESHOLD: Это порог, до которого мы ждем зарядки конденсатора.
    • Для зарядки до 63.2% от 5В (напряжение питания Arduino) это примерно 3.16В.
    • Поскольку аналоговый вход Arduino имеет 10-битное разрешение (0-1023), 3.16В соответствует (3.16 / 5.0) * 1023 ≈ 646.6. Я округлил до 648 для запаса.
  6. setup():
    • Инициализация Serial для отладки (вывод данных в Serial Monitor).
    • Инициализация дисплея. Если дисплей не найден, программа остановится.
  7. loop():
    • Разрядка: Сначала chargePin устанавливается как OUTPUT в LOW, чтобы полностью разрядить конденсатор. Это важно для точных измерений.
    • Подготовка к зарядке: chargePin переводится в INPUT (высокоимпедансное состояние), позволяя конденсатору заряжаться через резистор от напряжения на analogPin.
    • Измерение времени: micros() используется для измерения времени в микросекундах. Это обеспечивает достаточную точность для измерения небольших ёмкостей.
    • Цикл while: Ждет, пока напряжение на analogPin не достигнет VOLTAGE_THRESHOLD.
    • Расчет ёмкости:capacitance_uF = (float)(endTime - startTime) / R_VALUE_KOHM;
      • Если startTime и endTime в микросекундах, а R_VALUE_KOHM в килоомах, то результат будет в нанофарадах (нФ). Это происходит из-за того, что 1 нФ = 1 кОм * 1 нс, а у нас мкс и кОм, поэтому 1 мкс / 1 кОм = 1 нФ.
      • Затем код проверяет, если ёмкость больше 1000 нФ, то переводит её в микрофарады (мкФ) для более удобного отображения.
    • Вывод на OLED и Serial: Результаты выводятся на дисплей и в Serial Monitor.
    • delay(1000): Задержка между измерениями.

Важные замечания и улучшения:

  • Точность резистора: Точность измерения напрямую зависит от точности известного резистора. Используйте прецизионные резисторы или измерьте их фактическое сопротивление мультиметром.
  • Диапазон измерений: Этот метод лучше всего работает для конденсаторов ёмкостью от нескольких нанофарад (нФ) до нескольких сотен микрофарад (мкФ).
    • Для пикофарад (пФ) нужны более сложные схемы (например, с осциллятором или высокочастотным измерением).
    • Для очень больших ёмкостей (тысячи мкФ) время зарядки будет очень долгим, и micros() может переполниться (около 70 минут). Для таких ёмкостей лучше использовать millis() и другие методы.
  • Помехи: Аналоговые измерения чувствительны к шумам. Убедитесь, что проводка короткая и надёжная.
  • Сброс конденсатора: Перед каждым измерением убедитесь, что конденсатор полностью разряжен. Добавленный digitalWrite(chargePin, LOW); delay(10); делает это.
  • Полярность электролитических конденсаторов: Электролитические конденсаторы имеют полярность. Подключайте их правильно, иначе они могут выйти из строя.

Этот код является хорошей отправной точкой. Загрузите его, подключите всё по схеме и попробуйте измерить несколько конденсаторов! Дайте знать, если возникнут вопросы.

Author: admin

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *