#include <avr/wdt.h>
#include <MFRC522.h>
#include <DFPlayer_Mini_Mp3.h>
#define BUSY_PIN 4 // Пин BUSY для MP3 пдеера
#define RST_PIN 9 // Пин RST для rfid модуля
#define SS_PIN 10 // Пин SS для rfid модуля
#define RX 2 // назначить пин RX SoftSerial
#define TX 3 // назначить пин TX SoftSerial
#define modeRes 11 // пин для сброса памяти ключей
#define look_PIN 5 // номер пина для подключения к нему реле открытия замка
#define blue_PIN 8
#define green_PIN 7
#define red_PIN 6
#define interval 2000 // интервал сброса RFID модуля в мкс
#define time_reset_mp3 600000 // интервал сброса MP3 плеера
#define volume 25 // громкость MP3 от 0 до 30
#define equalizer 0 // эквалайзер(POP=1) от 0 до 5 Normal/Pop/Rock/Jazz/Classic/Bass
#define sumName 7 // количество имен пользователей записанных на флешке начинаются с 0001.mp3, 0002.mp3 ... и т.д.
uint32_t rebootTimer=0, oldTime=0; // Переменная для таймера MFRC522 rfid(SS_PIN, RST_PIN); // Назначить пины SS и RST SoftwareSerial mySerial(RX, TX); // назначить пины RX, TX
SoftSerial
void setup()
{
// pinMode(look_PIN, OUTPUT); // пин для подключения реле открытия замка
// digitalWrite(look_PIN, LOW);
pinMode(red_PIN, OUTPUT);
pinMode(green_PIN, OUTPUT);
pinMode(blue_PIN, OUTPUT);
pinMode(modeRes, INPUT_PULLUP); // пин сброса памяти ключей mySerial.begin (9600); // Инициализация
Soft Serial mp3_set_serial (mySerial);
delay (1000);
mp3Reset(); // инициализация плеера
uint8_t memClear = digitalRead(modeRes); // проверяем состояние пина сброса памяти
if(!memClear) // Если установлена перемычка на GND и пин D11
{
digitalWrite (green_PIN, HIGH);
digitalWrite (red_PIN, HIGH);
eeprom_write_byte(0, 255); // то обнуляем счетчик ключей
mp3play (113, 13000); // память обнулена
while(true); // зависаем и ждем нажатия reset
}
SPI.begin(); // Инициализация
SPI firstStart(); // проверка наличия Мастер ключа и добавление его mp3play (109, 9500); // система активирована //
Serial.begin(115200); // Инициализация Serial //
wdt_enable(WDTO_8S); }
void loop()
{
digitalWrite (green_PIN, HIGH);
digitalWrite (red_PIN, HIGH);
digitalWrite (blue_PIN, HIGH);
uint8_t sumKey = eeprom_read_byte(0); // считываем из EEPROM с адреса 0 информацию о количестве сохраненных ключей
uint32_t master = ReadEEPROM_Long(1); // читаем из EEPROM uid мастер ключа
uint32_t uid_tmp = ReadUID(); // ждем когда приложат ключ к считывателю и Читаем UID ключа
//Serial.println(sumKey);
//Serial.println(master);
//Serial.println(uid_tmp);
if(uid_tmp == master)
{
digitalWrite (red_PIN, LOW);
digitalWrite (blue_PIN, LOW);
addKey(sumKey); // если к считывателю поднесли мастер ключ, то переходим в режим добавления новых ключей
}
if(sumKey>=0 && uid_tmp != master) // если в EEPROM больше 1 ключа и UID прочитан с RFID то сравниваем все имеющиеся в EEPROM ключи со считанным 1
{
uint8_t nameKey = searchKey(sumKey, uid_tmp); // считываем все ключи по очереди из EEPROM и сравниваем их с UID приложенного к считывателю ключа
if(nameKey > 0) // в nameKey номер(индекс) ключа
{
sumKey = eeprom_read_byte(nameKey*5); // читаем из EEPROM привязанное к uid имя пользователя //
digitalWrite (look_PIN, HIGH); // открываем замок
digitalWrite (green_PIN, LOW);
mp3play (106, 1480); // фраза "Здравствуйте"
mp3play (sumKey, 1200); // проигрываем привязанное имя пользователя к uid
mp3play (107, 5000); // фраза "Добро пожаловать"
//digitalWrite (look_PIN, LOW); // закрываем замок
} else {
digitalWrite (red_PIN, LOW);
mp3play(104, 6500); } // фраза "Доступ запрещен, Ключ не найден"
}
if (millis() - oldTime > time_reset_mp3) // интервал таймера для сброс плеера
{
oldTime = millis();
} }
//*********************************************
uint32_t ReadUID(void) // опрашиваем считыватель каждую 0,2сек
{ for (;;) // бесконечный цикл
{
ResetRFID(); // перезагружаем RFID модуль каждые 2 секунды delay(100);
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) // Если метка найдена и она прочитана
{ return uidTolong(); // прервать цикл и возвратить UID
} } }
//-----------------------------------------
uint8_t searchKey( uint8_t sumKey, uint32_t uid ) // поиск ключа в EEPROM. sumKey-количество сохраненных ключей вEEPROM
{
for (uint8_t i = 1; i <= sumKey; i++)
{
uint32_t tmp=ReadEEPROM_Long(i*5+1); //читаем по очереди все сохраненные UID и сравниваем их с UID полученным c
RFID if(tmp == uid) { return i; } // сравниваем считанный из памяти UID с прочитанным UID и если найден, то возвращаем номер совпавшего ключа
}
return 0; // если в базе нет такого ключа то возвращаем 0
}
//---------------------------------------
void addKey(uint8_t sumKey) // sumKey-количество сохраненных ключей в EEPROM
{
mp3play(101, 15000); // для добавления нового UID после того как услышите имя которое нужно привязать к UID поднесите ключ к считывателю RFID
for (uint8_t i = 1; i <= sumName; i++) // перебираем все имена по очереди
{
mp3play(110, 1000); // проигрывание звука next
ResetRFID();
pinMode(TX, OUTPUT); // восстанавливаем выход для TX
mp3_play (i); // проигрываем в фоновом режиме в порядке возрастания все записанные на флешку имена
mp3_set_volume (volume); // устанавливаем заданную громкость
for (uint8_t ti = 0; ti < 20; ti++) // цикл таймер, 20*100мс=2 сек на опрос считывателя RFID пока проигрывается имя пользователя
{
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) // Если определена метка и она прочитана
{ uint32_t uid = uidTolong(); // преобразуем uid из массива в ulong uint8_t dub = searchKey(sumKey, uid); // ищем в EEPROM совпадение, проверяем ключ на дубли
if(dub == 0) // если такого ключа нет в памяти то добавляем его { // или если ключ есть то в dub номер ключа
sumKey++; // инкрементируем счетчик ключей
eeprom_write_byte(0, sumKey); // счетчик ключей в EEPROM eeprom_write_byte(sumKey*5, i); // сохраняем в EEPROM привязанное к ключу имя
WriteEEPROM_Long (sumKey*5+1, uid); // сохраняем UID ключа в EEPROM delay(500); // для того,что бы имя проигралось до конца mp3play(103, 4500); // фраза "новый ключ сохранен" mp3play(112, 9000); // фраза "мастер режим завершен" return; } else { digitalWrite (blue_PIN, HIGH); delay(1000);
mp3play(111, 9000); // прочитанный ключ уже имеется в системе digitalWrite (red_PIN, HIGH);
mp3play(112, 9000); // фраза "мастер режим завершен" return; } } delay(100);
} }
mp3play(108, 9000); // Время ожидание ключа истекло.
}
//----------------------------------------
void firstStart(void) { uint8_t tmp = eeprom_read_byte(0); // проверяем записан ли мастер ключ в EEPROM if(tmp==255) // если его там нет, то нужно добавить { mp3play(100, 12500); // фраза добавить мастер ключ uint32_t uid_tmp = ReadUID(); // прочитать UID мастер ключа со считывателя RFID if( uid_tmp > 0 ) // если ключ прочитан то записываем его в EEPROM { eeprom_write_byte (0, 0); // по адресу 000 записываем счетчик ключей не более 51 шт.------------------ WriteEEPROM_Long (1, uid_tmp); // по адресу 001 может быть записан только мастер ключ mp3play(102, 3500); // фраза мастер ключ добавлен } } }
//----------------------------------------
void ResetRFID(void) // Таймер сброса RFID защита от зависания
{
if (millis() - rebootTimer > interval) // интервал таймера
{
rebootTimer = millis(); // Обновляем таймер
digitalWrite(RST_PIN, HIGH); // Сбрасываем модуль delayMicroseconds(100); // длительность сброса 100 мкс digitalWrite(RST_PIN, LOW); // Отпускаем сброс
rfid.PCD_Init(); // Инициализируем
RFID rfid.PCD_AntennaOn(); // Включаем антенну
} }
//---------------------------------------
void mp3Reset(void) // можно так же использовать как остановку трека { mp3_reset (); delay (1000);
// mp3_set_device(2); // 2-работа с SD Card. 1/2/3/4/5 U/SD/AUX/SLEEP/FLASH
// mp3_DAC (true); mp3_set_EQ (equalizer); // эквалайзер Normal/Pop/Rock/Jazz/Classic/Bass
delay (100);
mp3_set_volume (volume); // устанавливаем громкость
delay (200);
pinMode(TX, INPUT_PULLUP); // Отключаем TX, что бы в динамике исчез шум/наводка
}
//---------------------------------------
void mp3play(uint16_t track, uint16_t time)
{
pinMode(TX, OUTPUT); // восстанавливаем выход TX
mp3_play(track); // проиграть трек //
mp3_set_volume (volume); // устанавливаем заданную громкость //wdt_reset(); delay(time); // длительность проигрывания // mp3_set_volume (0); // выключаем звук, что бы не было шума в динамике
pinMode(TX, INPUT_PULLUP); // Отключаем TX, что бы в динамике исчез шум/наводка
}
//---------------------------------------
uint32_t uidTolong(void)
{
uint32_t uid_l
uid_l // преобразуем uid массив в тип uint32_t uid_l << 8) | rfid.uid.uidByte[2]); uid_l << 8) | rfid.uid.uidByte[1]);
return (uid_l << 8) | rfid.uid.uidByte[0])); //прервать цикл и передать UID
}
void WriteEEPROM_Long(uint8_t addr, uint32_t data) //преобразовать из long и сохранить в
EEPROM { eeprom_write_byte((uint8_t*)addr, data & 0xFF); eeprom_write_byte((uint8_t*)addr+1, (data & 0xFF00) >> 8); eeprom_write_byte((uint8_t*)addr+2, (data & 0xFF0000) >> 16); eeprom_write_byte((uint8_t*)addr+3, (data & 0xFF000000) >> 24); } uint32_t ReadEEPROM_Long(uint8_t addr) // считываем значение из EEPROM и преобразуем в long { uint32_t ir_code = eeprom_read_byte((uint8_t*)addr+3); ir_code = (ir_code << 8) | eeprom_read_byte((uint8_t*)addr+2); ir_code = (ir_code << 8) | eeprom_read_byte((uint8_t*)addr+1); return ((ir_code << 8) | eeprom_read_byte((uint8_t*)addr)); }