// https://randomnerdtutorials.com/esp32-pir-motion-sensor-interrupts-timers/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
// defining functions
void cleardisplay ();
void printdata (float i, float j, float k);
#define SCREEN_WIDTH 128 // SSD1306 definition
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define timeSeconds 2 // past 3 sec PIR active
#define DHTPIN 4
#define DHTTYPE DHT22
const int led = 26;
const int motionSensor = 27;
DHT dht(DHTPIN, DHTTYPE);
unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;
boolean motion = false;
boolean showstatus = false;
boolean f;
float h, t;
// ISR - Interrupt Service Routine - activated throughout "interrupt"
// interrupt function - needs no call for activation
// activation through RISING current on pin "motionSensor"
// IRAM_ATTR: would be too slow if it was stored in flash memory
void IRAM_ATTR detectsMovement() { // Checks if motion was detected
digitalWrite(led, HIGH); // led HIGH
motion = true;
startTimer = true; // start the timer
lastTrigger = millis();
} // IRAM-ATTR = interrupt code in RAM
void setup() {
Serial.begin(115200);
dht.begin();
// PIR Motion Sensor mode INPUT_PULLUP
pinMode(motionSensor, INPUT_PULLUP);
// Set motionSensor pin as interrupt, assign interrupt function and set RISING mode
attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);
// arguments: 1) motionSensor-pin, 2) function to execute, 3) when: RISING
// LOW Triggers the interrupt whenever the pin is LOW
// HIGH Triggers the interrupt whenever the pin is HIGH
// CHANGE Triggers the interrupt whenever the pin changes value, from HIGH to LOW or LOW to HIGH
// FALLING Triggers the interrupt when the pin goes from HIGH to LOW
// RISING Triggers the interrupt when the pin goes from LOW to HIGH
pinMode(led, OUTPUT); // led-pin HIGH & motion false are
digitalWrite(led, LOW); // triggers
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // display setup
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.display();
delay (1000);
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
cleardisplay ();
}
// ------------------ l o o p --------------------
void loop() {
h = dht.readHumidity();
t = dht.readTemperature();
f = dht.readTemperature(true);
if (isnan(h) || isnan(t) || isnan(f)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
now = millis();
if((digitalRead(led) == HIGH) && (motion == true)) {
Serial.println("MOTION DETECTED!");
cleardisplay ();
printdata (t,h,5);
delay ((timeSeconds+1)*1000);
cleardisplay ();
// motion = true;
}
// Turn off the LED after the number of seconds defined in the timeSeconds variable
if(startTimer && (now - lastTrigger > (timeSeconds*1000))) {
Serial.println("Motion stopped...");
digitalWrite(led, LOW);
startTimer = false;
motion = false;
}
}
void printdata (float i, float j, float k) {
const int border = 2;
const int leftborder = 6;
const int texthight = 10;
display.drawRect(border, border, SCREEN_WIDTH-border, SCREEN_HEIGHT-border, WHITE);
display.setCursor(leftborder, 2*texthight);
display.print("Temp.: ");
display.print(i);
display.print(" °C");
display.setCursor(leftborder, 3*texthight);
display.print("Humid.: ");
display.print(j);
display.print(" %");
display.setCursor(leftborder, 4*texthight);
display.print("Press.: ");
display.print(k);
display.println(" hPa");
display.display(); // 4. set display active
}
void cleardisplay () {
display.clearDisplay(); // clears display buffer 1) first step
display.display(); // sets output active 2) second step
}