#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// --- Pin Definitions ---
#define DS18B20_SUPPLY_PIN 4 // DS18B20 #1 (подавальний) - data pin
#define DS18B20_RETURN_PIN 15 // DS18B20 #2 (зворотний) - data pin
#define OLED_SDA 21
#define OLED_SCL 22
// --- Constants ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define OLED_ADDR 0x3C
// Heat meter simulation constants
const float FLOW_RATE = 0.5; // м³/год (витрата теплоносія)
const float SPECIFIC_HEAT = 4186.0; // Дж/(кг·°C) (теплоємність води)
const float WATER_DENSITY = 1000.0; // кг/м³
// --- Objects ---
OneWire oneWireSupply(DS18B20_SUPPLY_PIN);
OneWire oneWireReturn(DS18B20_RETURN_PIN);
DallasTemperature sensorSupply(&oneWireSupply);
DallasTemperature sensorReturn(&oneWireReturn);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// --- Variables ---
float totalEnergy = 0.0; // Накопичена теплова енергія (кВт·год)
unsigned long lastMeasure = 0; // Час останнього вимірювання
unsigned long measureCount = 0; // Лічильник вимірювань
void setup() {
Serial.begin(115200);
Serial.println("====================================");
Serial.println(" IoT Heat Meter - Simulation");
Serial.println(" Kompiuternyi Praktykum #1");
Serial.println("====================================");
// Init I2C for OLED
Wire.begin(OLED_SDA, OLED_SCL);
// Init OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println("ERROR: SSD1306 OLED not found!");
while (true) { delay(100); }
}
// Splash screen
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(10, 5);
display.println("IoT Heat Meter");
display.setCursor(10, 20);
display.println("Praktykum #1");
display.setCursor(10, 40);
display.println("Initializing...");
display.display();
// Init DS18B20 sensors
sensorSupply.begin();
sensorReturn.begin();
Serial.print("Supply sensor count: ");
Serial.println(sensorSupply.getDeviceCount());
Serial.print("Return sensor count: ");
Serial.println(sensorReturn.getDeviceCount());
delay(2000);
lastMeasure = millis();
}
void loop() {
// Request temperatures from both sensors
sensorSupply.requestTemperatures();
sensorReturn.requestTemperatures();
float tSupply = sensorSupply.getTempCByIndex(0);
float tReturn = sensorReturn.getTempCByIndex(0);
bool supplyOk = (tSupply != DEVICE_DISCONNECTED_C);
bool returnOk = (tReturn != DEVICE_DISCONNECTED_C);
// Calculate heat energy
unsigned long now = millis();
float dtSeconds = (now - lastMeasure) / 1000.0;
lastMeasure = now;
measureCount++;
float deltaT = 0;
float powerW = 0;
if (supplyOk && returnOk) {
deltaT = tSupply - tReturn;
// P = G [м³/год] * ρ [кг/м³] * c [Дж/(кг·°C)] * ΔT [°C] / 3600
// Result in Watts
powerW = FLOW_RATE * WATER_DENSITY * SPECIFIC_HEAT * deltaT / 3600.0;
if (powerW < 0) powerW = 0; // No negative heat
// Accumulate energy: E += P * dt (convert to kWh)
float energyIncrement = powerW * dtSeconds / 3600000.0; // W·s → kWh
totalEnergy += energyIncrement;
}
// --- Display on OLED ---
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
// Header
display.setCursor(0, 0);
display.print("== HEAT METER ==");
// Supply temperature
display.setCursor(0, 12);
display.print("T1(sup): ");
if (supplyOk) {
display.print(tSupply, 1);
display.print(" C");
} else {
display.print("ERR!");
}
// Return temperature
display.setCursor(0, 22);
display.print("T2(ret): ");
if (returnOk) {
display.print(tReturn, 1);
display.print(" C");
} else {
display.print("ERR!");
}
// Delta T
display.setCursor(0, 32);
display.print("dT: ");
if (supplyOk && returnOk) {
display.print(deltaT, 1);
display.print(" C");
} else {
display.print("---");
}
// Thermal power
display.setCursor(0, 42);
display.print("Power: ");
display.print(powerW, 1);
display.print(" W");
// Accumulated energy
display.setCursor(0, 52);
display.print("Energy: ");
if (totalEnergy < 1.0) {
display.print(totalEnergy * 1000, 1);
display.print(" Wh");
} else {
display.print(totalEnergy, 3);
display.print(" kWh");
}
display.display();
// --- Serial output ---
Serial.println("-----------------------------");
Serial.print("Measurement #");
Serial.println(measureCount);
Serial.print("T1 (supply): ");
Serial.print(supplyOk ? String(tSupply, 2) + " C" : "ERROR");
Serial.println();
Serial.print("T2 (return): ");
Serial.print(returnOk ? String(tReturn, 2) + " C" : "ERROR");
Serial.println();
Serial.print("Delta T: ");
Serial.print(deltaT, 2);
Serial.println(" C");
Serial.print("Flow rate: ");
Serial.print(FLOW_RATE, 2);
Serial.println(" m3/h");
Serial.print("Thermal pwr: ");
Serial.print(powerW, 1);
Serial.println(" W");
Serial.print("Total energy: ");
Serial.print(totalEnergy * 1000, 2);
Serial.print(" Wh (");
Serial.print(totalEnergy, 4);
Serial.println(" kWh)");
delay(2000);
}