The code is ready, but I’m well advised to ask you for review.
It is still unclear to me why the timer does not call - as defined - after expiration the function readAgain,
but only over the test isActive.
If you still have suggestions for my ToDos fire free
In fact, this example can also be adapted to all sorts of open windows/doors. Take it with a smile.
// Reed-Switch with Particle Photon and a buzzer - works with v0.7.0-rc.3 without Libaries
// Ingo Lohs, v1.0 v. 16.11.2017
// Project to indicate a beep on an open toilet lid
// it is more of an educational measure not to block the toilet from the masses
// ToDo:
// * how often was the toilet used? Particle.Publish, counter
// * how long was the lid actually open (measurement of time)
// * why is it necessary to check an active timer, why does not it jump to the readAgain function after the timer expires?
#include "application.h" // necessary when using Timer
const int REED_PIN_IN = D2; // Pin connected to reed switch
const int REED_PIN_OUT = D4; // Pin connected to reed switch
const int BUZZER_PIN_OUT = A4; // Pin connected to a buzzer and to GND // On the Photon, P1 and Electron, this function works on pins D0, D1, D2, D3, A4, A5, WKP, RX and TX
const int LED_PIN = D7; // Pin internal LED
const int standard_toilette_session = 10000; // how many seconds is your standard time for you? (= 10 seconds)
unsigned long lastmillis = 0; // time for iteration the loop
Timer timer(standard_toilette_session, readAgain); // https://docs.particle.io/reference/firmware/photon/#software-timers
// **************
void setup()
{
Serial.begin(9600);
pinMode(REED_PIN_IN, INPUT);
pinMode(REED_PIN_OUT, OUTPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN_OUT, OUTPUT);
}
// **************
void loop()
{
if ((millis() - lastmillis) > 1000) {
lastmillis = millis();
readData();
}
}
// **************
void readData()
{
int proximity = digitalRead(REED_PIN_IN); // Read the state of the switch
if (proximity == HIGH) // If the pin reads HIGH, the switch is open // the pin reads LOW, the switch is closed
{
Serial.println(">> Session begin >> Switch is open");
// Particle.publish("Toilette", "toilet is in use right now", PRIVATE); // now the Particle Cloud knows that you have gone to the toilet
// timer starts
timer.start(); // https://docs.particle.io/reference/firmware/photon/#start-
// At the end of the expiring timer reset the timer and call the function readAgain
if (timer.isActive() == false) // https://docs.particle.io/reference/firmware/photon/#isactive--1
{
timer.reset();
readAgain();
}
}
else if (proximity == LOW)
{
Serial.println(">> normal Status >> Switch is closed");
timer.stop(); // stops a running timer.
digitalWrite(LED_PIN, LOW); // Turn the LED off
}
else
{
Serial.println("Switch ERROR Reading Value");
timer.stop(); // stops a running timer.
digitalWrite(LED_PIN, LOW); // Turn the LED off
}
}
// ************** At the end of the expiring timer, the open lid is checked again
void readAgain()
{
int lid_open = digitalRead(REED_PIN_IN); // Read the state of the switch
if (lid_open == HIGH)
// ALARM // the user reads newspaper or something else and blocks the toilet or in the worst case does not close the lid
{
digitalWrite(LED_PIN, HIGH); // Turn the LED on - optical warning
// Particle.publish("Toilette", "forgot to close the lid", PRIVATE); // the Particle Cloud knows what you not learned
// Buzzer on - accustical warning
// notes in the melody:
// https://docs.particle.io/reference/firmware/photon/#tone-
int melody[] = {1908,2551,2551,2273,2551,0,2024,1908}; //C4,G3,G3,A3,G3,0,B3,C4
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {4,8,8,4,4,4,4,4};
// iterate over the notes of the melody:
for (int thisNote = 0; thisNote < 8; thisNote++)
{
// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000/noteDurations[thisNote];
tone(BUZZER_PIN_OUT, melody[thisNote], noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(BUZZER_PIN_OUT);
}
// the annoying melody is played continuously until the lid is closed
}
else
// all is fine // the user closed the lid during the defined delay time
{
digitalWrite(LED_PIN, LOW); // Turn the LED off
noTone(BUZZER_PIN_OUT); // Turn the Buzzer off
}
}