Изучаем Arduino: инструметы и методы технического волшебства - [75]

Шрифт
Интервал

13.4.2. Программа для регистратора

Для нашего регистратора необязательно читать переменные с карты памяти, поэтому можно удалить данную часть кода. В программу необходимо добавить проверку


- 297 -

Рис. 13.23. Крепление блоков регистратора возле входной двери показаний ИК-датчика расстояния и определение величины их изменения за время между опросами. Если изменение есть, можно предположить, что кто-то вошел или вышел из комнаты. Нужно выбрать порог изменения аналоговых показаний датчика для точного определения факта прохода через дверь. Я экспериментально определил, что для моей установки изменение значения аналогового сигнала более чем на 75 единиц является достаточным признаком для фиксации движения (у вас, возможно, будет по-другому). Чтобы надежно установить момент прохода, необходимо проверять датчик достаточно часто.

Я рекомендую записывать данные на SD-карту только в момент появления человека, а в остальное время обновлять журнал лишь с определенной периодичностью.

При этом будет обеспечен хороший баланс между объемом хранимой информации и точностью работы. Плата Arduino опрашивает датчик расстояния через 50 мс (и добавляет единицу к текущему столбцу каждый раз при обнаружении движения). Если движение не обнаруживается, записываем ноль в текущий столбец через 1 секунду (в отличие от 50 мс).

В листинге 13.7 приведена программа входного регистратора, работающая согласно описанному алгоритму.

Листинг 13.7. Программа входного регистратора - entrance_logger.ino

// Программа входного регистратора

#include

// Подключение библиотеки SD

#include

// Для работы с RTC

#include "RTClib.h" // Подключение библиотеки RTC

- 298 -

// Подключение устройств SPI и I>2C с контактами по умолчанию

// SD-карта SPI контакты

// RTC - стандартные I>2C контакты

const int CS PIN=10;

// SS для переходника SD

const int SD_POW_PIN =8;

// Питание Для SD

const int RTC_POW_PIN =A3; // Питание для платы RTC

const int RTC_GND_PIN =А2.; // Земля для платы RTC

const int IR_PIN=0; // ИК-датчик расстояния к аналоговому входу A0

// Создать объект RTC

RTC_DS1307 RTC;

// Инициализация переменных для даты/времени

String year, month, day, hour, minute, second, time, date;

// Инициализация переменных для ИК-датчика расстояния

int raw = 0;

int raw_prev = 0;

boolean active = false;

int update_time = 0;


void setup()

{

Serial.begin(9600);

Serial.println(F("Initializing Card"));

// Настроить контакты CS и питания как выходы

pinMode(CS_PIN, OUTPUT);

pinMode(SD_POW_PIN, OUTPUT);

pinMode(RTC_POW_PIN, OUTPUT);

pinMode(RTC_GND_PIN, OUTPUT);

// Установка питания карты и RTC

digitalWrite(SD_POW_PIN, HIGH);

digitalWrite(RTC_POW_PIN, HIGH);

digitalWrite(RTC_GND_PIN, LOW);

// Инициализация Wire и RTC

Wire.begin();

RTC.begin();

// Если RTC не запущены, загрузить дату/время с компьютера

if ( ! RTC. isrunning())

{

Serial.println(F("RTC is NOT running!"));

RTC.adjust(DateTime(__DATE__, __TIME__));

}

// Инициализация карты SD

if ( !SD.begin(CS_PIN))

{

Serial.println(F("Card Failure"));

return;

}

- 299 -

Serial.println(F("Card Ready"));

// Запись заголовка

File dataFile = SD.open("log.csv", FILE_WRITE);

if (dataFile)

{

dataFile.println(F("\nNew Log Started!"));

dataFile.println(F("Date,Time,Raw,Active"));

dataFile.close();

// Запись в последовательный порт для отладки

Serial.println(F("\nNew Log Started!"));

Serial.println(F("Date,Tirne,Raw,Active"));

}

else

{

Serial.println(F("Couldn't open log file"));

}

}

void loop()

{

// Получить значение даты и времени и перевести в строковые значения

DateTirne datetirne = RTC.now();

year = String(datetirne.year(), DEC);

rnonth = String(datetime.rnonth(), DEC);

day = String(datetirne.day(), DEC);

hour = String(datetirne.hour(), DEC);

rninute = String(datetime.rninute(), DEC);

second = String(datetime.second(), DEC);

// Собрать строку текущей даты и времени

date = year + "/" + rnonth + "/" + day;

time = hour + ":" + rninute + "·" + second;

// Собрать данные движения

raw = analogRead(IR_PIN);

// При изменении значения более чем на 75 между показаниями

// фиксируем факт прохода через дверь.

if (abs(raw-raw_prev) > 75)

active

true;

else

active=false;

raw_prev=raw;

// Открыть лог-файл и записать в него.

if (active || update_tirne == 20)

File dataFile=SD.open("log.csv", FILE_WRITE);

if (dataFile)

{

dataFile.print(date);

- 300 -

dataFile.print(F(","));

dataFile.print(time);

dataFile.print(F(","));

dataFile.print(raw);

dataFile.print(F(","));

dataFile.println(active);

dataFile.close();

// Вывод в последовательный порт для отладки

Serial.print(date);

Serial.print(F(","));

Serial.print(time);

Serial.print(F(","));

Serial.print(raw);

Serial.print(F(","));

Serial.println(active);

}

else

{

Serial.println(F("Couldn't open log file"));

}

update_time = 0;

}

delay(50);

update_time++;

}

13.4.3. Анализ зарегистрированных данных

После загрузки программы на плату Arduino установите регистратор возле двери и дайте поработать некоторое время. Когда наберется достаточное количество данных, вставьте SD-карту в компьютер и откройте лог-файл CSV в программе просмотра электронных таблиц. Предполагая, что на карте записаны данные для одного дня, можно построить график активности движения от времени. Пока никто не проходит через дверь, значение остается равным нулю. Когда кто-нибудь входит или выходит из комнаты, значение подскакивает до единицы, и можно точно узнать, когда это случилось. Процедура построения графика зависит от выбранного графического приложения. Я создал онлайн-таблицу, которая будет рисовать график. Чтобы воспользоваться этим сервисом, вам необходимо иметь учетную запись Google.