Вольтметр на Arduino Uno

Вольтметр на Arduino Uno, з діапазоном вимірювання від 0V до 30 V з відображення на символьному дисплеї LCD1602.

Діапазон АЦП (Аналого Цифровий Прертворювач) у Arduino Uno від 0 вольт до напруги живлення 5V. Отже для вимірювання напруги в діапазоні 0 – 5 вольт, не потрібно додаткових компонентів. Для вимірювання більших напруг, сигнал можна подати через резестивний подільник напруги.

Схема підключення

R1 – 51 kOm

R2 – 10 kOm

D1 – стабілітрон 5.1V, для захисту GPIO мікроконтролора.

Розрахунок подільника напруги

Подільник напруги розраховується за формулою.

Uout = Uin * (R2 / (R1 + R2))

Uin – максимальна вхідна напруга яку ми хочемо вимірювати

Uout – при максимальній Uin має бути менше або рівне 5V

R1 – резистор верхнього плеча подільника

R2 – резистор нижнього плеча подільника

Спробуєм розрахувати, резистори підбираєм з стандартиних рядів. Так при резисторах R1 = 33кОм, R2 = 6.8кОм, вхідна напруга 30V.

30 = (6800 / (33000 + 6800)) = 5,125;

Uin більше 5V.

Змінемо резистори R1 = 51кОм, R2 = 10кОм, вхідна напруга 30V.

30 * (10000 / (51000 + 10000)) = 4,918;

10 кОм та 51 кОм резистори стандартного ряду, вихідна напруга, при 30V вхідній буде менша 5V

Коефіцієнт ділення напруги.

К = Uout / Uin = R2 / (R1 + R2)

Обмеження використання резистивного подільника

Номінали опорів подільника повинен бути в 100 – 1000 разів менше ніж навантаження, в нашому випадку вхідний опір аналогового GPIO у Arduino Uno 1МОм.

Занадто малі значення опорів, призводять до нагрівання резисторів, втрат активної потужоності, зниження ККД, як результат зниження точності результату вимірювання.

Код програми

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define R1 51000.0  // Верхнє плече подільника напруги
#define R2 10000.0  // Нижнє плече подільника напруги
#define SEMPLES 20  // Кількість разів вибірки
#define VOLT_PIN A0 // PIN вольтметра

LiquidCrystal_I2C lcd(0x27, 16, 2);  

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.setCursor(2, 0);
  lcd.print("Voltmeter");
  lcd.setCursor(5, 1);
  lcd.print("Qazf.com.ua");
  delay(2000);
  lcd.clear();
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print("Voltmeter");
  lcd.setCursor(11, 1);
  lcd.print("V");
}
void display_v(float v)
{
  if (v < 10)
  {
    lcd.setCursor(5, 1);
    lcd.print(" ");
    lcd.setCursor(6, 1);
    lcd.print(v);
  }
  else
  {
    lcd.setCursor(5, 1);
    lcd.print(v);
  }
}

float read_v()
{
  int sum = 0;
  for (int i = 0; i < SEMPLES; i++)
  {
    sum += analogRead(VOLT_PIN);
  }
  int raw = sum / SEMPLES;
  float v_calc = raw * ((R1 + R2) / R2);
  float v = v_calc * (5.0 / 1023.0);
  return v;
}

void loop()
{
  float volt = read_v();
  display_v(volt);
  delay(200);
}

Додамо другий канал для вимірювання 0 – 5V

Резестивний подільник збільшує діапазон вимірівуння напруги, але знижує точність. Тому ми додамо ще один канал з діапазоном вимірювання 0 – 5V для точнішого вимірювання.

Схема підключення

R1 – 51 кОм

R2 – 10 кОм

D1, D2 – стабілітрони 5.1V, для захисту GPIO мікроконтролора.

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define R1 51000.0      // Верхнє плече подільника напруги
#define R2 10000.0      // Нижнє плече подільника напруги
#define SEMPLE30S 20    // Кількість разів вибірки
#define VOLT_PIN_CH1 A0 // PIN вольтметра
#define VOLT_PIN_CH2 A1 // PIN вольтметра

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
  lcd.init();
  lcd.backlight();
  lcd.setCursor(2, 0);
  lcd.print("Voltmeter");
  lcd.setCursor(5, 1);
  lcd.print("Qazf.com.ua");
  delay(2000);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("CH1");
  lcd.setCursor(14, 0);
  lcd.print("V");
  lcd.setCursor(1, 1);
  lcd.print("CH2");
  lcd.setCursor(14, 1);
  lcd.print("V");
}
void display_v(float v1, float v2)
{
  if (v1 < 10)
  {
    lcd.setCursor(8, 0);
    lcd.print(" ");
    lcd.setCursor(9, 0);
    lcd.print(v1);
  }
  else
  {
    lcd.setCursor(9, 0);
    lcd.print(v1);
  }

  lcd.setCursor(9, 1);
  lcd.print(v2);
}

float read_v1()
{
  int sum = 0;
  for (int i = 0; i < SEMPLES; i++)
  {
    sum += analogRead(VOLT_PIN_CH1);
  }
  int raw = sum / SEMPLES;
  float v_calc = raw * ((R1 + R2) / R2);
  float v = v_calc * (5.0 / 1023.0);
  return v;
}

float read_v2()
{
  int sum = 0;
  for (int i = 0; i < SEMPLES; i++)
  {
    sum += analogRead(VOLT_PIN_CH2);
  }
  int raw = sum / SEMPLES;
  float v = raw * (5.0 / 1023.0);
  return v;
}

void loop()
{
  float v1 = read_v1();
  float v2 = read_v2();
  display_v(v1, v2);
  delay(200);
}

Як працює

  int sum = 0;

  for (int i = 0; i < SEMPLES; i++)
  {
    sum += analogRead(analogPin);
  }

  int raw = sum / SEMPLES;

Зчитоємо дані певну кількість разів, кількість визначаться перемінною SEMPLES. Сумоємо зчитані дані та ділимо на SEMPLES, отримуємо середнє значення (фільтр від випадкового шуму).

 float v_calc = raw * (5.0 / 1023.0);

Конвертуємо зчитані дані у напругу.

float v = v_calc * ((R1 + R2) / R2);

Якщо підключено через подільник напруги, зчитане значення напруги множимо на коефіціент подільника.

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *