Arduino Nano miernik napięcia 0-30V z OLED I2C – kod, schemat, kalibracja

Pytanie

napisz program miernika napięcia dla arduino nano z wyświetlaczem oled i2c

Odpowiedź Sztucznej Inteligencji


Bezpośrednia odpowiedź na pytanie

Tak — poniżej masz gotowy, działający program miernika napięcia dla Arduino Nano z wyświetlaczem OLED I2C.
Program:

  • mierzy napięcie na wejściu A0,
  • wyświetla wynik na OLED SSD1306 128x64 I2C,
  • stosuje uśrednianie próbek, aby odczyt był stabilny,
  • jest przystosowany do pomiaru napięć do około 30 V DC przy użyciu dzielnika napięcia.

Kluczowe punkty

  • Dla napięć powyżej 5 V konieczny jest dzielnik napięcia.
  • Zalecam:
    • R1 = 56 kΩ
    • R2 = 10 kΩ
  • Dobrze dodać:
    • kondensator 100 nF między A0 i GND dla filtracji zakłóceń.
  • Kod zakłada wyświetlacz SSD1306, adres I2C 0x3C.

Szczegółowa analiza problemu

Poniżej przedstawiam kompletny projekt: połączenia, kod, wyjaśnienie działania i uwagi kalibracyjne.

1. Założenia sprzętowe

Arduino Nano z ATmega328P ma przetwornik ADC 10-bitowy, czyli:

\[
ADC \in \langle 0,\ 1023 \rangle
\]

Przy domyślnym napięciu odniesienia:

\[
V_{REF} \approx 5.0\text{ V}
\]

bezpośrednio można mierzyć tylko napięcia z zakresu:

\[
0 \text{ V} \; \text{do} \; 5 \text{ V}
\]

Jeżeli chcesz mierzyć wyższe napięcie, musisz zastosować dzielnik rezystorowy.

2. Zalecany dzielnik napięcia

Proponuję:

  • R1 = 56 kΩ
  • R2 = 10 kΩ

Współczynnik przeliczenia:

\[
k = \frac{R1 + R2}{R2} = \frac{56k + 10k}{10k} = 6.6
\]

Zatem napięcie wejściowe:

\[
V{IN} = V{A0} \cdot 6.6
\]

Dla 30 V na wejściu:

\[
V_{A0} = 30 \cdot \frac{10}{56+10} \approx 4.55\text{ V}
\]

czyli bezpiecznie poniżej 5 V.

3. Połączenia

OLED I2C

OLED Arduino Nano
VCC 5V
GND GND
SDA A4
SCL A5

Dzielnik napięcia

Element Połączenie
badane napięcie „+” do R1
R1 = 56 kΩ między wejściem napięcia a punktem pomiarowym
punkt pomiarowy do A0
R2 = 10 kΩ między punktem pomiarowym a GND
badane napięcie „−” do GND Arduino

Dodatkowo zalecane

  • 100 nF między A0 i GND
  • wspólna masa badanego układu i Arduino

4. Gotowy program

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// =========================
// Konfiguracja OLED
// =========================
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
#define OLED_ADDRESS  0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// =========================
// Konfiguracja pomiaru
// =========================
const byte VOLTAGE_PIN = A0;
// Dzielnik napięcia:
// Vin --- R1 ---+--- A0
//               |
//              R2
//               |
//              GND
const float R1 = 56000.0;   // 56k
const float R2 = 10000.0;   // 10k
// Ustaw rzeczywiste napięcie zasilania Arduino.
// Zmierz multimetrem napięcie między 5V i GND.
// Na początek zostaw 5.00, potem skalibruj.
const float VREF = 5.00;
// Dodatkowy współczynnik kalibracyjny.
// Po porównaniu z dobrym multimetrem możesz np. ustawić 0.995 lub 1.008
const float CAL_FACTOR = 1.000;
// Parametry pracy
const byte NUM_SAMPLES = 32;
const unsigned long REFRESH_MS = 200;
const float MAX_DISPLAY_VOLTAGE = 30.0;  // skala paska
unsigned long lastRefresh = 0;
// =========================
// Funkcja pomiaru napięcia
// =========================
float measureVoltage()
{
  unsigned long sum = 0;
  for (byte i = 0; i < NUM_SAMPLES; i++)
  {
    sum += analogRead(VOLTAGE_PIN);
    delayMicroseconds(200);
  }
  float adcAvg = (float)sum / NUM_SAMPLES;
  // Napięcie na pinie A0
  float vA0 = adcAvg * (VREF / 1023.0);
  // Napięcie wejściowe przed dzielnikiem
  float vIn = vA0 * ((R1 + R2) / R2);
  // Kalibracja
  vIn *= CAL_FACTOR;
  // Odcinanie drobnych śmieci przy 0V
  if (vIn < 0.02) vIn = 0.0;
  return vIn;
}
// =========================
// Rysowanie ekranu
// =========================
void drawScreen(float voltage)
{
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  // Nagłówek
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.print(F("Miernik napiecia DC"));
  display.drawLine(0, 10, 127, 10, SSD1306_WHITE);
  // Duzy odczyt
  display.setTextSize(3);
  display.setCursor(0, 18);
  display.print(voltage, 2);
  display.setTextSize(2);
  display.print(F("V"));
  // Pasek
  int barWidth = (int)(voltage / MAX_DISPLAY_VOLTAGE * 120.0);
  if (barWidth < 0) barWidth = 0;
  if (barWidth > 120) barWidth = 120;
  display.setTextSize(1);
  display.setCursor(0, 46);
  display.print(F("Zakres wyswietlania: 0-30V"));
  display.drawRect(4, 56, 120, 6, SSD1306_WHITE);
  display.fillRect(4, 56, barWidth, 6, SSD1306_WHITE);
  display.display();
}
void setup()
{
  Serial.begin(115200);
  pinMode(VOLTAGE_PIN, INPUT);
  analogReference(DEFAULT); // dla klasycznego Nano: odniesienie do VCC (~5V)
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS))
  {
    Serial.println(F("Blad inicjalizacji OLED"));
    while (true) { }
  }
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(2);
  display.setCursor(8, 16);
  display.println(F("WOLTOMIERZ"));
  display.setTextSize(1);
  display.setCursor(22, 42);
  display.println(F("Arduino Nano + OLED"));
  display.display();
  delay(1500);
}
void loop()
{
  if (millis() - lastRefresh >= REFRESH_MS)
  {
    lastRefresh = millis();
    float voltage = measureVoltage();
    drawScreen(voltage);
    Serial.print(F("Napiecie: "));
    Serial.print(voltage, 3);
    Serial.println(F(" V"));
  }
}

5. Dlaczego ten kod jest poprawny technicznie

Ten program jest lepszy od najprostszej wersji z kilku powodów:

  • używa uśredniania 32 próbek, więc wskazanie nie „skacze”,
  • rozdziela logikę pomiaru i logikę wyświetlania,
  • uwzględnia dzielnik napięcia,
  • umożliwia kalibrację przez VREF i CAL_FACTOR,
  • ogranicza wpływ drobnych zakłóceń przy napięciu bliskim 0 V.

6. Korekta typowych błędów z przykładowych odpowiedzi

W dostarczonych odpowiedziach były dwie częste nieścisłości, które warto skorygować:

  • Dzielnik 30 kΩ / 7.5 kΩ nie nadaje się bezpiecznie do 30 V, bo da na wejściu Arduino około 6 V.
    Taki układ nadaje się raczej do około 25 V, a nie 30 V.
  • W bibliotece Adafruit inicjalizacja SSD1306 powinna wyglądać tak:
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

a nie w formie charakterystycznej dla innych bibliotek lub błędnych makr.


Aktualne informacje i trendy

Na podstawie dostarczonych odpowiedzi online i praktyki projektowej można przyjąć, że obecnie najczęściej w takich projektach stosuje się:

  • wyświetlacze OLED SSD1306 128x64 I2C,
  • biblioteki:
    • Adafruit_GFX
    • Adafruit_SSD1306
  • adres I2C wyświetlacza zwykle:
    • 0x3C
    • rzadziej 0x3D

W praktyce konstrukcyjnej coraz częściej zamiast prostego pomiaru na wejściu ADC stosuje się również:

  • ADS1115 — zewnętrzny przetwornik ADC o lepszej rozdzielczości,
  • INA219 / INA226 — gdy trzeba mierzyć jednocześnie napięcie i prąd,
  • programową filtrację:
    • średnia krocząca,
    • filtr medianowy,
    • histereza odświeżania wskazań.

Dla prostego hobbystycznego woltomierza Arduino Nano + SSD1306 nadal jednak jest rozwiązaniem wystarczającym.


Wspierające wyjaśnienia i detale

Jak działa przeliczenie napięcia

Arduino mierzy napięcie na pinie A0:

\[
V{A0} = \frac{ADC}{1023} \cdot V{REF}
\]

Ponieważ na A0 trafia napięcie już podzielone przez dzielnik, napięcie rzeczywiste wynosi:

\[
V{IN} = V{A0} \cdot \frac{R1 + R2}{R2}
\]

Po podstawieniu:

\[
V{IN} = \frac{ADC}{1023} \cdot V{REF} \cdot \frac{R1 + R2}{R2}
\]

To właśnie realizuje kod.

Dlaczego warto dać kondensator 100 nF

Wejście analogowe i długi przewód pomiarowy łatwo zbierają zakłócenia.
Kondensator 100 nF z A0 do GND tworzy prosty filtr RC, który:

  • stabilizuje odczyt,
  • zmniejsza migotanie wskazań,
  • poprawia powtarzalność pomiaru.

Dlaczego nie użyłem bardzo dużych rezystorów

Zbyt duża rezystancja dzielnika pogarsza warunki pracy wejścia ADC.
ATmega328P lubi źródło o niezbyt dużej impedancji.
Układ 56 kΩ / 10 kΩ daje kompromis między:

  • bezpieczeństwem,
  • małym poborem prądu,
  • poprawnym próbkowaniem ADC.

Aspekty etyczne i prawne

W tym projekcie najważniejsze są kwestie bezpieczeństwa elektrycznego.

Bezpieczeństwo

  • Ten układ nadaje się do niskich napięć DC, np.:
    • zasilacze,
    • akumulatory 12 V / 24 V,
    • moduły elektroniczne.
  • Nie wolno podłączać go bezpośrednio do:
    • sieci 230 V AC,
    • instalacji energetycznych,
    • obwodów bez wspólnej, bezpiecznej masy,
    • układów wysokonapięciowych.

Ograniczenia prawne i użytkowe

  • Taki miernik nie jest przyrządem wzorcowanym.
  • Nie powinien być używany jako jedyne narzędzie pomiarowe w:
    • diagnostyce bezpieczeństwa,
    • przemyśle,
    • zastosowaniach medycznych,
    • systemach krytycznych.

Praktyczne wskazówki

Jak uruchomić

  1. Zainstaluj biblioteki:
    • Adafruit GFX
    • Adafruit SSD1306
  2. Podłącz OLED do A4/A5.
  3. Zbuduj dzielnik:
    • 56 kΩ
    • 10 kΩ
  4. Wgraj program.
  5. Zmierz multimetrem napięcie pinów 5V-GND na Arduino.
  6. Wpisz tę wartość do VREF.

Jak skalibrować

Jeżeli multimetr pokazuje 12.00 V, a Arduino 11.82 V, to:

\[
CAL_FACTOR = \frac{12.00}{11.82} \approx 1.015
\]

Wtedy ustaw:

const float CAL_FACTOR = 1.015;

Najlepsze praktyki

  • użyj rezystorów 1% zamiast 5%,
  • prowadź krótkie przewody pomiarowe,
  • dodaj kondensator 100 nF przy A0,
  • nie doprowadzaj do A0 więcej niż 5 V,
  • zostaw zapas bezpieczeństwa — praktycznie nie przekraczaj 30 V.

Typowe problemy

  • OLED nic nie wyświetla
    • sprawdź adres I2C: 0x3C lub 0x3D,
    • sprawdź SDA i SCL.
  • Wynik pływa
    • brak wspólnej masy,
    • brak kondensatora 100 nF,
    • za długie przewody.
  • Zaniżony lub zawyżony wynik
    • błędne wartości VREF,
    • tolerancja rezystorów,
    • zły stosunek R1/R2 wpisany w kodzie.

Ewentualne zastrzeżenia lub uwagi dodatkowe

  • Program mierzy tylko napięcie dodatnie względem GND.
  • Nie mierzy napięcia przemiennego AC.
  • Nie mierzy napięć ujemnych.
  • Dokładność jest ograniczona przez:
    • tolerancję rezystorów,
    • dokładność VREF,
    • szumy ADC,
    • jakość zasilania Arduino.

Jeżeli potrzebujesz większej dokładności, warto przejść na:

  • zewnętrzny ADC,
  • osobne źródło odniesienia,
  • kalibrację wielopunktową.

Sugestie dalszych badań

Jeżeli chcesz rozbudować projekt, kolejne sensowne kroki to:

  • pomiar prądu i mocy,
  • zapis wyników do pamięci lub przez UART,
  • alarm przekroczenia napięcia,
  • automatyczna kalibracja,
  • pomiar akumulatora z ikoną stanu,
  • zastosowanie ADS1115 dla wyższej rozdzielczości,
  • dodanie ochrony wejścia:
    • rezystor szeregowy,
    • transil,
    • ogranicznik przepięć.

Można też przygotować wersję:

  • do 0–5 V bez dzielnika,
  • do 0–50 V z innym dzielnikiem,
  • z wyświetlaczem SH1106,
  • z biblioteką U8g2.

Krótkie podsumowanie

Najprostsza poprawna realizacja miernika napięcia dla Arduino Nano i OLED I2C to:

  • OLED SSD1306 na A4/A5,
  • pomiar na A0,
  • dzielnik 56 kΩ / 10 kΩ dla zakresu około 0–30 V DC,
  • uśrednianie próbek i kalibracja VREF.

Podałem Ci gotowy, praktyczny i technicznie poprawny program.
Jeśli chcesz, mogę od razu przygotować także:

  1. wersję uproszczoną,
  2. wersję dokładniejszą z ADS1115,
  3. schemat połączeń w formie ASCII lub rysunku,
  4. wersję do zakresu 0–50 V.

Oceń odpowiedź:
Zastrzeżenie: Odpowiedzi udzielone przez sztuczną inteligencję (model językowy) mogą być niedokładne i wprowadzające w błąd. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi powinny być zweryfikowane przez użytkownika.

Zadaj dodatkowe pytanie Sztucznej Inteligencji

Czekaj (2min)...