Продолжение работы над проектом СКУД “MAX”.
Arduino. Система контроля и управления доступом.
Arduino. СКУД «MAX v2.0»
Не всегда удобно и целесообразно ставить проводные считыватели в тех местах, где просятся к установки беспроводные модули. Поэтому дошла очередь до создания беспроводной версии считывателя.
Итак, для беспроводного модуля не требуется материнский модуль, по этому вся обработка происходит в одном устройстве.
Выбор на чем делать – на ESP8266 или ESP32? А не нужно выбирать, сделаем на обоих платформах.
Итак, нам потребуются следующие компоненты:
1. esp8266 nodemcu v3 (был в наличии такой, но ничего не мешает и сделать на D1 mini)
2. Мини Rc522 Rfid (мне по душе такой миниатюрный модуль)
3. Для второго варианта плата ESP-WROOM-32
4. Несколько Rfid карточек которые идут в комплекте с модулями
Схема подключения к esp8266:
ESP8266 | RFID |
D4 | SDA |
D5 | SCK |
D7 | MOSI |
D6 | MISO |
GND | GND |
D3 | RST |
3.3v | 3.3v |
Для работы Rfid нужна стандартная библиотека MFRC522.h
#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "GyverTimer.h" // подключаем библиотеку
GTimer myTimer(MS); // создать миллисекундный таймер (ms) (по умолч. в режиме интервала)
const char* ssid = "videooko.net";
const char* password = "*********";
const uint_fast16_t DEVID = 999;
#define RST_PIN 27 // Configurable, see typical pin layout above
#define SS_PIN 25 // Configurable, see typical pin layout above
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
MFRC522::MIFARE_Key key;
unsigned long uidDec, uidDecTemp;
int run = 0;
// Init array that will store new NUID
byte nuidPICC[4];
/**
* Helper routine to dump a byte array as hex values to Serial.
*/
void printHex(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
/**
* Helper routine to dump a byte array as dec values to Serial.
*/
void printDec(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], DEC);
}
}
String server = "cardserver.videooko.net";
String unitID_in;
void handleReceivedMessage(String message) {
StaticJsonDocument<500> doc; //Memory pool. Поставил наугад для демонстрации
DeserializationError error = deserializeJson(doc, message);
// Test if parsing succeeds.
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
/* 0 - GOOD not errors
1 - Card is not connect to people
2 - Card not activ
3 - Card Blocking
4 - Card UNKNOWN */
Serial.println();
Serial.println("----- DATA FROM CARD SERVER!!! ----");
const char* kod = doc["kod"];
Serial.print("KOD CARD: ");
Serial.println(kod);
int c_status = doc["status"];
Serial.print("Status card: ");
Serial.println(c_status);
int c_error = doc["error"];
Serial.print("Error: ");
Serial.println(c_error);
Serial.println("------------------------------");
}
void sendhttpserver(){
HTTPClient http;
String getstr;
//Serial.println ("SEND to Server!!!");
String mystr = String(uidDec);
getstr = "http://"+server+"/check.php";
http.begin(getstr);
int httpCode = http.POST(getstr);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
// Data to send with HTTP POST
String httpRequestData = "kod="+mystr+"&id="+DEVID+"&GPS1=0&GPS2=0";
int httpResponseCode = http.POST(httpRequestData);
//Serial.println(httpRequestData);
if (httpCode > 0) {
// выводим ответ сервера
String payload = http.getString();
// Serial.println(httpCode);
// Serial.println(payload);
handleReceivedMessage(payload);
}
else {
Serial.println("Ошибка HTTP-запроса");
}
// освобождаем ресурсы микроконтроллера
http.end();
}
void setup() {
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println();
Serial.println();
Serial.println(F("==========================================="));
SPI.begin(); // Init SPI bus
rfid.PCD_Init(); // Init MFRC522
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}
Serial.println(F("This code scan the MIFARE Classsic NUID."));
Serial.print(F("Using the following key:"));
printHex(key.keyByte, MFRC522::MF_KEY_SIZE);
Serial.println('\n');
WiFi.begin(ssid, password); // Connect to the network
while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect
delay(500);
Serial.print('.');
}
Serial.println('\n');
Serial.println("Connection established");
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
//LedsSetup();
myTimer.setInterval(3000);
}
void loop() {
if (myTimer.isReady()) rfid.PCD_Init();
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( ! rfid.PICC_IsNewCardPresent()){
//Serial.println(F("PICC_IsNewCardPresent"));
//delay(5);
return;
}
// Verify if the NUID has been readed
if ( ! rfid.PICC_ReadCardSerial()){
Serial.println(F("PICC_ReadCardSerial"));
delay(5);
return;
}
Serial.print(F("PICC type: "));
MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
Serial.println(rfid.PICC_GetTypeName(piccType));
// Check is the PICC of Classic MIFARE type
if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&
piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
Serial.println(F("Your tag is not of type MIFARE Classic."));
return;
}
if (rfid.uid.uidByte[0] != nuidPICC[0] ||
rfid.uid.uidByte[1] != nuidPICC[1] ||
rfid.uid.uidByte[2] != nuidPICC[2] ||
rfid.uid.uidByte[3] != nuidPICC[3] ) {
Serial.println(F("A new card has been detected."));
uidDec = 0;
// Store NUID into nuidPICC array
for (byte i = 0; i < 4; i++) {
nuidPICC[i] = rfid.uid.uidByte[i];
uidDecTemp = rfid.uid.uidByte[i];
uidDec = uidDec * 256 + uidDecTemp;
}
// Serial.print("Card UID: ");
// Serial.println(uidDec); // Выводим UID метки в консоль.
run=1;
unitID_in = uidDec;
}
else {
Serial.println(F("Card read previously."));
run=0;
}
// Halt PICC
rfid.PICC_HaltA();
// Stop encryption on PCD
rfid.PCD_StopCrypto1();
if (run){
//Serial.println("RUN GAME - 1");
sendhttpserver();
run=0;
}
}
Данный скетч сканирует карту и по http отправляет данные на указанный сервер. Ответ приходит JSON его и разбираем.
В процессе работы с этим скетчем мне пришел запрос на разработку проекта учета проезда в городском транспорте жителей льготной категории. Такой себе бюджетный проект небольшого города в Украине. Им понравились наработки моего проекта СКУД на ардуине, поэтому заинтересовались на его базе внедрить аналогичную систему на городском транспорте.
Определены следующие условия
1. Транспорт уже имеет или будет иметь у себя штатный WIFI с подключением к интернету.
2. Все запросы должны передаваться в режиме онлайн на сервер, где будет происходить проверка электронных карт.
3. Считыватели в транспорте не хранят никакую информацию о картах. Режим работы только онлайн.
4. Разработка веб приложения для работы с картами.
Минимальный веб интерфейс для работы с картами.
Итак, считыватель… Для визуализации обработки ошибок и исключительных ситуаций считыватель необходимо укомплектовать дополнительной световой индикацией.
Первая проба считывателя
Доработанная версия в корпусе
На этом этапе проект пока остановился в ожидании дальнейшей заинтересованности в его развитии или внедрения.
Добрый день! Почему при компиляции скетча ошибка? –
sketch_sep16a:86:16: error: no matching function for call to ‘HTTPClient::HTTPClient()’
86 | HTTPClient http;
Наверное не та библиотека