📘 Описание
Этот простой проект позволяет собрать цифровой вольтметр на базе Arduino, отображающий:
- текущее напряжение на аналоговом входе (до 5 В) если без делителя
- максимальное зафиксированное значение Напряжения
- шкалу в виде сегментов (как индикатор уровня)
- живой график изменения напряжения в нижней части экрана
Дополнительно добавлена кнопка сброса максимального значения, а на OLED 128×64 дисплее для лучшего отображения и визуализации добавлен график.
📋 Компоненты
📎 Функции проекта
- Отображение напряжения с точностью до 0.01 В
- Сохранение и отображение максимального значения
- Кнопка для сброса максимума
- Сегментированная шкала уровня (аналоговая индикация)
- РеалТайм график напряжения (как мини-осциллограф)
🧠 Принцип работы
- Напряжение считывается с пина A0 с помощью analogRead()
- Значение преобразуется в вольты и отображается
- В массиве graphBuffer[] сохраняются последние значения
- На основе этого массива строится линейный график
- Кнопка сбрасывает максимум (антидребезг реализован через delay(300))
🔍 Как работает программа
1. Чтение напряжения и расчёт
Каждый цикл программа опрашивает аналоговый вход A0 при помощи функции analogRead(), которая возвращает значение от 0 до 1023, соответствующее напряжению от 0 до 5 В. Затем это значение преобразуется в вольты по формуле:
voltage = raw * (5.0 / 1023.0);
Максимальное значение сохраняется в переменной maxVoltage. Если текущее значение выше предыдущего максимума — оно перезаписывается. Таким образом, на экране всегда отображается пиковое напряжение с момента последнего сброса.
2. Отображение на дисплее
Программа строит интерфейс в несколько этапов:
- Верхняя часть дисплея — отображает текущие и максимальные значения напряжения в виде текста.
- Средняя часть — визуальный уровень напряжения в виде сегментной шкалы, где каждый сегмент активен в зависимости от уровня сигнала.
- Нижняя часть — график напряжения во времени, построенный с использованием массива graphBuffer[], в котором хранятся последние 128 измерений. Этот массив сдвигается каждый раз и отображается как ломаная линия, повторяя форму изменения напряжения.
Такой подход позволяет использовать OLED-дисплей максимально эффективно: информативно и красиво.
🧠 Дисплей
Размещение основных блоков отображения на экране OLED дисплея
🧾 Код скетча
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int analogPin = A0;
const int resetButtonPin = 2;
#define GRAPH_HEIGHT 20
#define GRAPH_WIDTH 128
uint8_t graphBuffer[GRAPH_WIDTH];
class VoltMeter {
private:
int pin;
float voltage;
float maxVoltage;
public:
VoltMeter(int analogInputPin) {
pin = analogInputPin;
voltage = 0.0;
maxVoltage = 0.0;
}
void measure() {
int raw = analogRead(pin);
voltage = raw * (5.0 / 1023.0);
if (voltage > maxVoltage) {
maxVoltage = voltage;
}
}
void resetMax() {
maxVoltage = voltage;
}
float getVoltage() {
return voltage;
}
float getMax() {
return maxVoltage;
}
};
VoltMeter voltmeter(analogPin);
void updateGraph(float voltage) {
for (int i = 0; i < GRAPH_WIDTH - 1; i++) {
graphBuffer[i] = graphBuffer[i + 1];
}
uint8_t newY = map(voltage * 100, 0, 500, 0, GRAPH_HEIGHT);
graphBuffer[GRAPH_WIDTH - 1] = newY;
}
void drawGraph() {
int baseY = SCREEN_HEIGHT - 1;
for (int x = 0; x < GRAPH_WIDTH - 1; x++) {
display.drawLine(x, baseY - graphBuffer[x], x + 1, baseY - graphBuffer[x + 1], SSD1306_WHITE);
}
}
void drawScale(float value) {
const int segments = 10;
const int startX = 0;
const int startY = 22;
const int segWidth = 10;
const int segHeight = 5;
const int gap = 2;
int activeSegments = map(value * 100, 0, 500, 0, segments);
for (int i = 0; i < segments; i++) {
int x = startX + i * (segWidth + gap);
if (i < activeSegments) {
display.fillRect(x, startY, segWidth, segHeight, SSD1306_WHITE);
} else {
display.drawRect(x, startY, segWidth, segHeight, SSD1306_WHITE);
}
}
}
void setup() {
pinMode(resetButtonPin, INPUT_PULLUP);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 28);
display.println("Digital Voltmeter");
display.display();
delay(1500);
}
void loop() {
voltmeter.measure();
if (digitalRead(resetButtonPin) == LOW) {
voltmeter.resetMax();
delay(300);
}
float voltage = voltmeter.getVoltage();
float maxVoltage = voltmeter.getMax();
updateGraph(voltage);
display.clearDisplay();
display.setCursor(0, 0);
display.print("Voltage: ");
display.print(voltage, 2);
display.println(" V");
display.setCursor(0, 10);
display.print("Max: ");
display.print(maxVoltage, 2);
display.println(" V");
drawScale(voltage);
drawGraph();
display.display();
delay(200);
}
Волтметр-Амперметр-Ватметр DC730
📦 Дополнительно
- Максимально допустимое напряжение на A0: 5 В! Используйте делитель, если измеряете больше напряжение.
- Можно модернизировать проект, добавив:EEPROM для сохранения максимума
Автонастройку масштаба графика
Зум на график или отображение средних значений
🔗 Связанные проекты
🔌 Вольтметр с OLED 128×32 без графика (упрощённый)
📈 Мини-осциллограф на Arduino (в разработке)