#include <Arduino.h>
#include <DHT.h>
#include <SD.h>
#include <SPI.h>
#define DHT_PIN 2
#define DHT_TYPE DHT22
#define PIR_PIN 3
#define SD_CS_PIN 8
#define MEASUREMENT_INTERVAL 60000
#define LOG_FILENAME "log.txt"
#define LOG_HEADERS " Temperatura | Vlažnost vazduha | Detekcija pokreta"
void interpretInputCommands();
void readAndDeleteFile();
void writeHeaders();
String formatLogValues(float temperature, float humidity, bool motionDetected);
DHT dht(DHT_PIN, DHT_TYPE);
unsigned long loggingInterval = MEASUREMENT_INTERVAL;
void setup()
{
pinMode(PIR_PIN, INPUT);
Serial.begin(9600);
while (!Serial)
;
Serial.println(F("Inicijalizacija SD kartice..."));
if (!SD.begin(SD_CS_PIN))
{
Serial.println(F("Greska pri inicijalizaciji SD kartice! Proverite vezu i karticu."));
while (true)
;
}
Serial.println(F("SD kartica inicijalizovana."));
Serial.println(LOG_HEADERS);
if (!SD.exists(LOG_FILENAME))
{
writeHeaders();
}
dht.begin();
}
void loop()
{
static unsigned long previousTimestamp = 0;
unsigned long currentTimestamp = millis();
static bool motionDetected = false;
static bool previousPirState = false;
bool currentPirState = digitalRead(PIR_PIN);
bool pirDelayPassed = currentTimestamp - previousTimestamp > 5000;
motionDetected |= currentPirState && !previousPirState;
motionDetected |= currentPirState && previousPirState && pirDelayPassed;
if (currentTimestamp - previousTimestamp >= loggingInterval)
{
previousTimestamp = currentTimestamp;
previousPirState = currentPirState;
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature))
{
Serial.println(F("Greska pri citanju DHT senzora! Proverite vezu."));
motionDetected = false;
return;
}
File logFile = SD.open(LOG_FILENAME, FILE_WRITE);
if (logFile)
{
String dataString = formatLogValues(temperature, humidity, motionDetected);
logFile.println(dataString);
logFile.close();
Serial.println(dataString);
}
else
{
Serial.println(F("Greška pri otvaranju log fajla za upis."));
}
motionDetected = false;
}
if (Serial.available())
{
interpretInputCommands();
}
}
/* Ideju za projekat sam uzeo od kolege Danilo Ivkovic */
void interpretInputCommands()
{
String command = Serial.readStringUntil('\n');
command.trim();
if (command.equalsIgnoreCase("READ"))
{
readAndDeleteFile();
}
else if (command.startsWith("SET_INTERVAL="))
{
int equalsIndex = command.indexOf('=');
if (equalsIndex != -1)
{
String intervalString = command.substring(equalsIndex + 1);
long newInterval = intervalString.toInt();
if (newInterval > 0)
{
loggingInterval = newInterval * 1000;
Serial.print(F("Interval logovanja promenjen na: "));
Serial.print(newInterval);
Serial.println(F(" sekundi."));
}
else
{
Serial.println(F("Nevalidan interval. Unesite pozitivan broj."));
}
}
else
{
Serial.println(F("Neispravan format komande SET_INTERVAL. Koristite: SET_INTERVAL=<broj-sekundi>"));
}
}
else
{
Serial.println(F("Nepoznata komanda. Dostupne komande: READ, SET_INTERVAL=<sekunde>"));
}
}
void readAndDeleteFile()
{
Serial.println(F("\n*** Početak log fajla ***"));
File logFile = SD.open(LOG_FILENAME, FILE_READ);
if (logFile)
{
while (logFile.available())
{
Serial.write(logFile.read());
}
logFile.close();
Serial.println(F("*** Kraj log fajla ***"));
if (SD.remove(LOG_FILENAME))
{
Serial.println(F("Log fajl je uspešno obrisan."));
}
else
{
Serial.println(F("Greska pri brisanju log fajla."));
}
}
else
{
Serial.println(F("Log fajl ne postoji ili je došlo do greške pri otvaranju za čitanje."));
}
}
void writeHeaders()
{
File logFile = SD.open(LOG_FILENAME, FILE_WRITE);
logFile.write(LOG_HEADERS);
logFile.close();
}
String formatLogValues(float temperature, float humidity, bool motionDetected)
{
char output[80];
String temperatureValue = String(temperature, 2);
String humidityValue = String(humidity, 2);
String motionDetectedValue = motionDetected ? "Pokret detektovan" : "Nema pokreta";
sprintf(output, " %14s°C | %15s%% | %17s", temperatureValue.c_str(), humidityValue.c_str(), motionDetectedValue.c_str());
return String(output);
}