Что для этого нам понадобятся:
- Arduino Nano (или любой другой совместимый Arduino).
- OLED-дисплей 128×64 (обычно на контроллере SSD1306, подключается по I2C).
- Конденсатор, ёмкость которого будем измерять.
- Резистор известного номинала (например, 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:
- Adafruit GFX Library (базовая графическая библиотека)
- 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 секунда перед следующим измерением }
Пояснения к коду:
- Подключение библиотек:
Wire.h
для I2C-связи,Adafruit_GFX.h
иAdafruit_SSD1306.h
для работы с OLED-дисплеем. - Настройка OLED:
#define SCREEN_WIDTH 128
и#define SCREEN_HEIGHT 64
: Определяют разрешение дисплея.Adafruit_SSD1306 display(...)
: Создает объект для работы с дисплеем. Адрес0x3C
(или0x3D
) — стандартный для многих SSD1306. Если дисплей не работает, проверьте его I2C-адрес.
- Пины для измерения:
chargePin (пин 2)
: Используется для управления зарядкой/разрядкой конденсатора.analogPin (пин A0)
: Аналоговый вход для измерения напряжения на конденсаторе.
R_VALUE_KOHM
:ОЧЕНЬ ВАЖНО! Укажите здесь точный номинал вашего резистора в килоомах (кОм). Чем точнее вы измерите этот резистор мультиметром, тем точнее будут измерения ёмкости.- Для ёмкостей в диапазоне нФ используйте резистор 100 кОм — 1 МОм.
- Для ёмкостей в диапазоне мкФ используйте резистор 10 кОм — 100 кОм.
VOLTAGE_THRESHOLD
: Это порог, до которого мы ждем зарядки конденсатора.- Для зарядки до 63.2% от 5В (напряжение питания Arduino) это примерно 3.16В.
- Поскольку аналоговый вход Arduino имеет 10-битное разрешение (0-1023), 3.16В соответствует
(3.16 / 5.0) * 1023 ≈ 646.6
. Я округлил до648
для запаса.
setup()
:- Инициализация
Serial
для отладки (вывод данных в Serial Monitor). - Инициализация дисплея. Если дисплей не найден, программа остановится.
- Инициализация
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);
делает это. - Полярность электролитических конденсаторов: Электролитические конденсаторы имеют полярность. Подключайте их правильно, иначе они могут выйти из строя.
Этот код является хорошей отправной точкой. Загрузите его, подключите всё по схеме и попробуйте измерить несколько конденсаторов! Дайте знать, если возникнут вопросы.