#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <PN532.h>
#include <PN532_HSU.h>
// Настройки OLED дисплея
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
// Настройки PN532 для ESP32-C3
#define PN532_HSU_BAUD 115200
#define PN532_TX_PIN 4 // GPIO4 для TX (подключен к RX PN532)
#define PN532_RX_PIN 5 // GPIO5 для RX (подключен к TX PN532)
// Настройки I2C для OLED - попробуем разные пины
#define OLED_SDA 8 // GPIO8 для SDA
#define OLED_SCL 9 // GPIO9 для SCL
// Альтернативные пины I2C
// #define OLED_SDA 10 // GPIO10 для SDA
// #define OLED_SCL 11 // GPIO11 для SCL
// Создание объектов
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
PN532_HSU pn532hsu(Serial1);
PN532 nfc(pn532hsu);
// Флаги для отслеживания состояния
bool oledInitialized = false;
bool pn532Initialized = false;
void setup() {
// Инициализация Serial для отладки
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Инициализация системы ESP32-C3...");
Serial.println("Проверка подключения модулей...");
// Даем время на стабилизацию питания
delay(1000);
// Инициализация I2C для OLED с правильными пинами
Wire.begin(OLED_SDA, OLED_SCL);
Wire.setClock(100000); // Уменьшаем скорость I2C до 100kHz для стабильности
// Попытка инициализации OLED дисплея с несколькими попытками
for (int attempt = 0; attempt < 3; attempt++) {
if(display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
oledInitialized = true;
Serial.println("OLED дисплей инициализирован");
break;
}
Serial.printf("Попытка %d: Ошибка инициализации OLED\n", attempt + 1);
delay(500);
}
if (!oledInitialized) {
Serial.println("OLED: Проверьте подключение:");
Serial.printf("SDA -> GPIO%d\n", OLED_SDA);
Serial.printf("SCL -> GPIO%d\n", OLED_SCL);
Serial.println("VCC -> 3.3V");
Serial.println("GND -> GND");
} else {
// Отображение приветствия на OLED
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("NFC Reader ESP32-C3");
display.println("OLED: OK");
display.display();
delay(1000);
}
// Инициализация PN532
Serial1.begin(PN532_HSU_BAUD, SERIAL_8N1, PN532_RX_PIN, PN532_TX_PIN);
nfc.begin();
// Проверка подключения PN532 с несколькими попытками
for (int attempt = 0; attempt < 3; attempt++) {
uint32_t versiondata = nfc.getFirmwareVersion();
if (versiondata) {
pn532Initialized = true;
// Вывод информации о модуле
Serial.print("Найден чип PN5");
Serial.println((versiondata>>24) & 0xFF, HEX);
Serial.print("Версия прошивки: ");
Serial.print((versiondata>>16) & 0xFF, DEC);
Serial.print('.');
Serial.println((versiondata>>8) & 0xFF, DEC);
// Настройка PN532
nfc.SAMConfig();
break;
}
Serial.printf("Попытка %d: PN532 не отвечает\n", attempt + 1);
delay(500);
}
if (!pn532Initialized) {
Serial.println("PN532: Проверьте подключение:");
Serial.printf("PN532 TX -> GPIO%d (RX)\n", PN532_RX_PIN);
Serial.printf("PN532 RX -> GPIO%d (TX)\n", PN532_TX_PIN);
Serial.println("PN532 VCC -> 3.3V");
Serial.println("PN532 GND -> GND");
}
// Отображение статуса на OLED
if (oledInitialized) {
display.clearDisplay();
display.setCursor(0,0);
display.println("System Status:");
display.print("OLED: ");
display.println(oledInitialized ? "OK" : "ERROR");
display.print("PN532: ");
display.println(pn532Initialized ? "OK" : "ERROR");
if (pn532Initialized) {
display.println("Ожидание метки...");
} else {
display.println("Проверьте PN532");
}
display.display();
}
Serial.println("---------------------");
if (pn532Initialized) {
Serial.println("Ожидание NFC метки...");
}
}
void printHex(uint8_t *data, uint8_t length) {
for (uint8_t i = 0; i < length; i++) {
if (data[i] < 0x10) {
Serial.print("0");
}
Serial.print(data[i], HEX);
if (i < length - 1) {
Serial.print(":");
}
}
}
void displayHex(uint8_t *data, uint8_t length) {
for (uint8_t i = 0; i < length; i++) {
if (data[i] < 0x10) {
display.print("0");
}
display.print(data[i], HEX);
if (i < length - 1) {
display.print(":");
}
}
}
void loop() {
if (!pn532Initialized) {
// Попытка переинициализации PN532
uint32_t versiondata = nfc.getFirmwareVersion();
if (versiondata) {
pn532Initialized = true;
Serial.println("PN532 переподключен!");
if (oledInitialized) {
display.clearDisplay();
display.setCursor(0,0);
display.println("PN532 подключен");
display.display();
delay(2000);
}
}
delay(1000);
return;
}
uint8_t success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
uint8_t uidLength;
// Поиск карты
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
if (success) {
Serial.println("Найдена NFC метка!");
// Вывод UID в Serial
Serial.print("UID Length: ");
Serial.print(uidLength, DEC);
Serial.println(" bytes");
Serial.print("UID Value: ");
printHex(uid, uidLength);
Serial.println();
// Определение типа карты
const char* cardType;
switch(uidLength) {
case 4: cardType = "MIFARE Classic"; break;
case 7: cardType = "MIFARE Ultralight"; break;
default: cardType = "Unknown Type"; break;
}
Serial.print("Тип карты: ");
Serial.println(cardType);
Serial.println("---------------------");
// Отображение на OLED если он работает
if (oledInitialized) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0);
display.println("NFC Tag Detected");
display.println("");
// Отображение типа карты
display.print("Type: ");
display.println(cardType);
// Отображение длины UID
display.print("UID Len: ");
display.println(uidLength);
// Отображение UID
display.print("UID: ");
displayHex(uid, uidLength);
display.display();
}
// Задержка перед следующим чтением
delay(3000);
// Возврат к экрану ожидания
if (oledInitialized) {
display.clearDisplay();
display.setCursor(0,0);
display.println("NFC Reader Ready");
display.println("Ожидание метки...");
display.display();
}
}
delay(500);
}