Общие сведения
В этом проекте мы соберём полуавтоматический напоминатель о выполнении процедуры гигиены рук. Он будет оповещать нас о необходимости мыть руки, кода мы или кто-нибудь ещё входит с лестничной площадки или улицы внутрь помещения.
Видео
Нам понадобится
- Датчик отрытой двери/окна
- Инфракрасный датчик препятствий
- Trema-модуль Pull Switch UP/DOWN
- Trema-модуль зуммер
- Trema-модуль светодиод RGB
- Trema-модуль датчик освещённости flash-i2c
- Trema Shield, для удобства подключения
- Arduino/Piranha UNO
Подключение
Для удобства подключения мы воспользуемся Trema Shield для Arduino.
Для начала подключим Trema Shield к Piranha UNO

Следующим шагом подключим датчик освещённости Flash-I2C к колодке I2C

Подключим RGB светодиод, зуммер и модуль подтяжки к указанным выводам
| RGB светодиод | Piranha UNO |
|---|---|
| G | GND |
| V | VCC |
| R | D4 |
| G | D5 |
| B | D6 |
| Зуммер | Piranha UNO |
|---|---|
| G | GND |
| V | VCC |
| S | D7 |
| Модуль Pull UP/DOWN | Piranha UNO |
|---|---|
| G | GND |
| V | VCC |
| 2 | 2 |

И, наконец подключим инфракрасный датчик препятствий и датчик открытой двери
Перед установкой инфракрасного датчика препятствий в прихожей необходимо настроить дальность срабатывания. Сделать это можно при помощи подстроечного резистора на самом датчике
| Датчик препятствий | Piranha UNO |
|---|---|
| Синий | GND |
| Коричневый | VCC |
| Чёрный | 3 |
| Датчик двери | Модуль Pull UP/DOWN |
|---|---|
| Провод 1 | GND |
| Провод 2 | 2 |
Переключатель модуля Pull UP/DOWN должен находиться в положении UP

Скетч проекта
// Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_I2C_DSL.
#include <Wire.h>
#include <iarduino_I2C_DSL.h>
// Определяем выводы, к которым подключены модули
#define PIN_DOOR 2
#define PIN_IR 3
#define PIN_R 4
#define PIN_G 5
#define PIN_B 6
#define PIN_ZUM 7
// Определяем интервалы
#define BLINK_INTERVAL 500
#define WASH_INTERVAL 20000
#define BEEP_INTERVAL_SHORT 200
#define BEEP_INTERVAL_LONG 2000
// Инстанцируем объект библиотеки датчика освещённости и препятсвий Flash-I2C
iarduino_I2C_DSL prox;
// Переменные для хранения текущих millis
unsigned long last_millis;
unsigned long wash_millis;
unsigned long beep_millis;
// Переменная счёта звукового оповещения
uint8_t zum_beep_count;
// Переменные состояния светодиодов
bool red_state;
bool blue_state;
bool green_state;
// Переменная состояния утсройства
uint8_t device_state;
// Определяем возможные состояния устройства
enum {
// Ожидание
wait,
// Оповещение
alert,
// Мытьё
washing,
// Завершение мытья
finish_wash
};
void setup()
{
Serial.begin(9600);
// Выключаем всё и устанавливаем значения по умолчанию
reset();
// Инициируем работу с датчиком освещённости и препятствий Flash-I2C
prox.begin();
}
void loop()
{
// Если режим ожидания, дверь открыта и в коридоре кто-то есть...
if (device_state == wait && checkDoor()) {
// Ждём две секунды
delay(2000);
// Если сработал инфракрасный датчик в прихожей...
if (checkIR()) {
// переключаем устройство в режим оповещения
device_state = alert;
}
}
// Если режим оповещения и датчик препятсвий ещё не сработал
if (device_state == alert && !readProx()) {
// Включить оповещение
beep();
blinkRedBlue();
}
// Если режим оповещения и датчик препятствий сработал
if (device_state == alert && readProx()) {
// Сохраняем время срабатывания
wash_millis = millis();
// Выключаем световое оповещение
ledsOff();
// Переводим режим в режим мытья
device_state = washing;
}
// Если режим мытья
if (device_state == washing) {
// Включаем крастный светодиод
blink(PIN_R);
// Выключаем звуковое оповещение
noBeep();
}
// Если пришло время заканчивать мытьё и датчик препятствий ещё не сработал
if (device_state == washing
&& millis() - wash_millis > WASH_INTERVAL
&& !readProx()) {
// Выключаем светодиоды
ledsOff();
// Переводим режим в режим завершения мытья
device_state = finish_wash;
}
// Если режим завершения мытья
if (device_state == finish_wash) {
// Включаем оповещение
beep();
blink(PIN_G);
}
// Если режим завершения и сработал датчик препятствий
if (device_state == finish_wash && readProx()) {
// Выключаем звуковое оповещение
noBeep();
// Включаем зелёный светодиод
solidGreen();
// Ждём две секунды
delay(2000);
// Перезапускаем устройство
reset();
}
delay(100);
}
// Функция сброса установок на изначальные
void reset()
{
zum_beep_count = 0;
last_millis = 0;
wash_millis = 0;
beep_millis = 0;
red_state = true;
blue_state = false;
green_state = false;
device_state = wait;
ledsOff();
noBeep();
}
// Функция проверки состояния двери
bool checkDoor()
{
if (digitalRead(PIN_DOOR) == HIGH)
return true;
else
return false;
}
// Функция проверки состояния датчика
bool checkIR()
{
if (digitalRead(PIN_IR) == LOW)
return true;
else
return false;
}
// Функция включения звукового оповещения
void beep()
{
int interval;
if (zum_beep_count < 3) {
interval = BEEP_INTERVAL_SHORT;
}
else if (zum_beep_count < 4) {
interval = BEEP_INTERVAL_LONG;
}
else {
zum_beep_count = 0;
}
if (millis() - beep_millis > interval) {
pinMode(PIN_ZUM, OUTPUT);
digitalWrite(PIN_ZUM, HIGH);
Serial.println(zum_beep_count);
zum_beep_count++;
beep_millis = millis();
}
else {
pinMode(PIN_ZUM, INPUT);
}
}
// Функция выключения звукового оповещения
void noBeep()
{
pinMode(PIN_ZUM, INPUT);
zum_beep_count = 0;
}
// Функция чтения датчика препятствий
bool readProx()
{
if (prox.getProximity() > 50)
return true;
else
return false;
}
// Функция светового оповещения
void blinkRedBlue()
{
pinMode(PIN_R, OUTPUT);
pinMode(PIN_G, OUTPUT);
if (millis() - last_millis > BLINK_INTERVAL) {
red_state = !red_state;
blue_state = !blue_state;
last_millis = millis();
}
digitalWrite(PIN_R, red_state);
digitalWrite(PIN_B, blue_state);
}
// Функция включения зелёного светодиода
void solidGreen()
{
pinMode(PIN_G, OUTPUT);
digitalWrite(PIN_G, HIGH);
}
// Функция моргания светодиодом
void blink(uint8_t pin)
{
pinMode(pin, OUTPUT);
if (millis() - last_millis > BLINK_INTERVAL) {
green_state = !green_state;
last_millis = millis();
}
digitalWrite(pin, green_state);
}
// Функция выключения светодиодов
void ledsOff()
{
pinMode(PIN_R, INPUT);
pinMode(PIN_G, INPUT);
pinMode(PIN_B, INPUT);
}

Обсуждение