Dvokanalni voltmetar s termometrom za Arduino

· #arduino #voltmetar #termometar #oled

Sadržaj

Dvokanalni voltmetar s termometrom izveden kao shield za Arduino Uno. Mjeri dva istosmjerna napona do 40 V i temperaturu te sve prikazuje na malom OLED zaslonu.

Dvokanalni voltmetar s termometrom na Arduinu Uno, spojen na dvije baterije od 9 V

Kako radi

Uređaj koristi 10-bitni A/D pretvornik Arduina. Za svako mjerenje očita se 16 uzoraka. Njihov se zbroj dijeli s 4, što softverskim oversamplingom daje 12-bitnu razlučivost. Pet takvih mjerenja zatim se usrednjuje i prikazuje na zaslonu, otprilike svakih 300 ms. Stvarno vrijeme jednog ciklusa prikazuje se u zadnjem retku zaslona.

Shema

Shema dvokanalnog voltmetra s termometrom

Ulazni kanali

Mjereni napon dovodi se na stezaljke CH1+ i CH1−. Na ulazu je djelitelj napona od pet otpornika (100 kΩ prema 10 kΩ + 1 kΩ + 100 Ω + 10 Ω) s omjerom 10 : 1. Uz referentni napon od 4,096 V to daje mjerno područje do 40 V.

Izlaz djelitelja ide na kondenzator za filtriranje (1 µF) i zaštitne Schottkyjeve diode 1N5819 prema VCC-u i masi, a zatim na pin A1 Arduina. Drugi kanal izveden je jednako i spojen je na pin A2.

Upozorenje

Ulaz je predviđen samo za istosmjerni napon do 40 V. Viši napon može oštetiti Arduino unatoč zaštitnim diodama.

Referentni napon

Za referentni napon koristi se TL431, trimerom R16 podešen na 4,096 V. Spojen je na pin AREF Arduina preko kratkospojnika JP1.

Termometar

Temperatura se mjeri NTC termistorom od 47 kΩ (B = 3435). Termistor i otpornik od 47 kΩ u seriji čine djelitelj napona čiji izlazni napon ovisi o temperaturi. Izlaz djelitelja spojen je na pin A0, a skica iz izmjerenog napona izračunava otpor termistora te iz njega temperaturu pomoću B-jednadžbe.

Zaslon

OLED zaslon SSD1306 (0,96", 128×64) spojen je na +5 V i masu te signalnim linijama SDA i SCL na odgovarajuće pinove Arduina (I²C).

Skica za Arduino

Skica koristi biblioteku U8g2 za upravljanje zaslonom.

two_channel_voltmeter.ino Preuzmi

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// *********************************************************
// Program:   two chanel voltmeter with thermometer
// Date:      01/09/2018
// Version:   1.0
// Author:    Elvis Baketa
// Description:
// *********************************************************

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

// WHITE OLED LCD 0.96" 128X64 I2C
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

unsigned long startTime;
unsigned long finishTime;

int updateDisplay = 0;
int samples = 16;
float resolution = 4096.0;
float voltageReference = 4.096;
float seriesResistor = 47000.00;

int analogValueCH0[16];
int analogValueCH1[16];
int analogValueCH2[16];
unsigned int averageAnalogValueCH0;
unsigned int averageAnalogValueCH1;
unsigned int averageAnalogValueCH2;
float voltageCH0 = 0.000;
float voltageCH1 = 0.000;
float voltageCH2 = 0.000;
float averageVoltageCH1 = 0.000;
float averageVoltageCH2 = 0.000;

float resistance = 0.000;
float temperature = 0.000;
float averageTemperature = 0.000;

void setup() {
  // put your setup code here, to run once:
  analogReference(EXTERNAL);
  u8g2.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  updateDisplay++;

  // read chanel one
  for(int i = 0; i < samples; i++) {
    analogValueCH0[i] = analogRead(A0);
    delay(1);
  }
  for(int l = 0; l < samples; l++) {
    averageAnalogValueCH0 += analogValueCH0[l];
  }
  averageAnalogValueCH0 /= 4;
  voltageCH0 = averageAnalogValueCH0 * (voltageReference / resolution);
  averageAnalogValueCH0 = 0;
  // convert volts to resistance
  resistance = voltageReference / voltageCH0 - 1;
  resistance = 1 / resistance;
  resistance = seriesResistor * resistance;
  // convert resistance to temperature in Kelvin
  temperature = log(resistance / seriesResistor);
  temperature = temperature * (1 / float(3435));
  temperature = temperature + (1 / (25 + 273.15));
  temperature = 1 / temperature;
  // convert Kelvin to Celsius
  // T(°C) = T(°K) - 273.15
  temperature = temperature - 273.15;
  averageTemperature += temperature;

  // read chanel two
  for(int j = 0; j < samples; j++) {
    analogValueCH1[j] = analogRead(A1);
    delay(1);
  }
  for(int m = 0; m < samples; m++) {
    averageAnalogValueCH1 += analogValueCH1[m];
  }
  averageAnalogValueCH1 /= 4;
  voltageCH1 = averageAnalogValueCH1 * (voltageReference / resolution);
  voltageCH1 *= 10;
  averageVoltageCH1 += voltageCH1;
  averageAnalogValueCH1 = 0;

  // read chanel three
  for(int k = 0; k < samples; k++) {
    analogValueCH2[k] = analogRead(A2);
    delay(1);
  }
  for(int n = 0; n < samples; n++) {
    averageAnalogValueCH2 += analogValueCH2[n];
  }
  averageAnalogValueCH2 /= 4;
  voltageCH2 = averageAnalogValueCH2 * (voltageReference / resolution);
  voltageCH2 *= 10;
  averageVoltageCH2 += voltageCH2;
  averageAnalogValueCH2 = 0;

  if(updateDisplay > 4) {
    // display data
    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_profont22_tf);
    averageTemperature /= updateDisplay;
    u8g2.setCursor(0, 16);
    u8g2.print("T ");
    u8g2.print(averageTemperature);
    u8g2.print(char(176));
    u8g2.print("C");
    averageVoltageCH1 /= updateDisplay;
    u8g2.setCursor(0, 32);
    u8g2.print("CH1 ");
    u8g2.print(averageVoltageCH1);
    u8g2.print("V");
    averageVoltageCH2 /= updateDisplay;
    u8g2.setCursor(0, 48);
    u8g2.print("CH2 ");
    u8g2.print(averageVoltageCH2);
    u8g2.print("V");
    u8g2.setCursor(0, 64);
    finishTime = millis() - startTime;
    u8g2.print(finishTime);
    u8g2.print(" ms");
    u8g2.sendBuffer();
    averageTemperature = 0.000;
    averageVoltageCH1 = 0.000;
    averageVoltageCH2 = 0.000;
    updateDisplay = 0;
    startTime = millis();
  }
}