Budujemy prosty omomierz na Arduino

Cześć, jako że starter kit jest blogiem edukacyjnym na którym prezentujemy projekty od tych najprostszych poprzez nieco bardziej skomplikowane, aż po gotowe do pracy urządzenia elektroniczne to dziś chciałbym zaprezentować coś z kategorii absolutnych podstaw :) Zbudujemy na Arduino omomierz.

Schemat połączenia

Jak widać do zbudowania omomierza potrzebujemy jedynie jednego rezystora (poza tym, którego rezystancję będziemy badać) oraz wyświetlacza 16×2 na I2C (wtedy już mamy miernik na wypasie :P). Z punktu widzenia kolejnych krokó ważne jest, aby rezystory były podłączone dokładnie tak jak na obrazku tj. rezystor o znanej rezystancji 10k Ohm pomiędzy masą a przewodem podłączonym do pinu A0, natomiast badany rezystor między przewodem podłączonym do pinu A0, a napięciem 5V z Arduino.

Prawo Ohma

Jest to prawo, z któym w elektronice spotykamy się już od samych podstaw. Każdy, kto nie chce spalić sobie wszystkich diod podłączonych do Arduino musi je znać :) Z prawa tego wynika pewien bardzo znany wzór: I = U / R. Prąd płynący w układzie jest ilorazem napięcia oraz rezystancji danego układu.

Nasz układ składa się z dwóch rezystorów połączonych szeregowo o wartościach, które oznaczymy R1 i R2. R1 będzie naszym znanym rezystorem, natomiast R2 badanym. Przez układ płynie prąd I. Prąd taki płynie zarówno przez R1 jak i R2. Zmienia się jedynie spadek napięcia w całym układzie jak i w każdym z rezystorów. Napięcie, które spada na całym układzie to napięcie pobrane z Arduino, czyli 5V – oznaczymy je jako U. Mając powyższe na uwadze możemy wyznaczyć poniższy wzór:

U / (R1 + R2) = U1 / R1

Mnożąc na krzyż wyjdzie nam kolejno:

(R1 + R2) * U1 = R1 * U

R1 + R2 = (R1 * U) / U1

R2 = ((R1 * U) / U1) – R1

I w ten oto sposób otrzymaliśmy wzór, którym posłużymy się do obliczania rezystancji naszego badanego rezystora.

Program

Zacznijmy od załączenia bibliotek do obsługi wyświetlacza I2C:

#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>

Teraz możemy zdefiniować kilka stałych, z których będziemy korzystali:

#define DISPLAY_REFRESH_PERIOD  1000    // Okres odswiezania wyswietlacza
#define PIN_RESISTANCE          A0      // Pin pomiarowy
#define LCD_ADDR                0x27    // Adres I2C wyświetlacza LCD
#define R1                      10000.0 // Rezystancja R1
#define U                       5.0     // Napiecie U

oraz zmienne:

LiquidCrystal_PCF8574 lcd(LCD_ADDR);  // Ekran LCD
unsigned long lastDisplayRefresh;     // Ostatni czas odświeżenia ekranu

W funkcji setup uruchamiamy port szeregowy oraz konfigurujemy ekran LCD:

void setup() {
  Serial.begin(9600);
  Wire.begin();
  lcd.begin(16, 2);
  lcd.setBacklight(true);
  lcd.clear();
}

natomiast w funkcji loop wyświetlamy co określony interwał zmierzoną rezystancję:

void loop() {
  if(millis() - lastDisplayRefresh >= DISPLAY_REFRESH_PERIOD) {
    String resistanceString = getResistanceString();
    displayResistance(resistanceString);
    displayResistanceSerial(resistanceString);
    lastDisplayRefresh = millis();
  }
}

Aby funkcja zadziałała będą nam potrzebne 3 inne. displayResistance oraz displayResistanceSerial służą do wyświetlenia wartości kolejno na ekranie LCD oraz na porcie szeregowym. Funkcja getResistanceString zwraca zmierzoną wartość w formie stringa.

Funkcje do wyświetlania prezentują się tak:

void displayResistance(String resistance) {
  lcd.clear();
  lcd.print("Omomierz");
  lcd.setCursor(0, 1);
  lcd.print(String("R2 = ") + resistance);
}

void displayResistanceSerial(String resistance) {
  Serial.println(String("R2 = ") + resistance);
}

W funkcji getResistanceString dzieje się cała ta matematyka, którą opisywałem w poprzedniej sekcji:

String getResistanceString() {
  int measurementCount = 10;
  double r2Sum = 0.0;
  for(int x = 0; x < measurementCount; x++) {
    double u1 = U * (analogRead(PIN_RESISTANCE)/1023.0);
    r2Sum += (U*R1/u1) - R1;
  }
  double r2 = r2Sum / measurementCount;
  return String(r2);
}

Dla zwiększenia dokładności obliczenia zapętliłem w forze, który w tym przypadku wykona się 10 razy. Następnie wynik tych 10 pomiarów zostaje uśredniony i zwrócony. Pewne wątpliwości może wzbudzić sposób obliczania napięcia U1. Skąd wzięło się dzielenie przez 1023.0? Jak wiemy Arduino wyposażone jest w 10 bitowy przetwornik ADC. Oznacza to, że dla napięcia 5V otrzymamy wartość 2 do potęgi 10, czyli właśnie 1023. Każde napięcie z przedziału 0-5V będzie zmierzone do proporcjonalnej wartości z przedziału 0-1023. Wystarczy więc, że podzielymy zmierzoną wartość przez wartość maksymalną, którą może zmierzyć przetwornik, a następnie całość pomnożymy przez liczbę woltów, która odpowiada maksymalnej wartości.

Praca domowa

Żeby lepiej zrozumieć działanie programu warto wykonać z nim jakieś proste ćwiczenia. Proponuję, żebyście we własnym zakresie dodali do licznika zamianę wartości w ohmach na wartość z przedrostkami np. dla zmieroznej wartości 2200 niech licznik wypisze 2.20 k, a dla wartości 220 Ohmów 220 bez żadnego dopisku. Pamiętajcie, że są też inne przedrostki takie jak mili, mega itp.

Dodatkowo zastanówcie się jak możnaby zwiększyć dokładność pomiarów. Podpowiedź: zwróćcie uwagę dlaczego w zwykłych miernikach często jest wybór zakresu pomiaru.