Как всегда проблемы с PN532.

314Zdec

✩✩✩✩✩✩✩
2 Сен 2025
2
0
Такая у меня история - стоит задача: прилепить считыватель nfc к контроллеру, считывать метки. Казалось бы - проще некуда и всё прекрасно работало, пока модуль был подключен к arduino. Но! Как только я поменял платформу на ESP32 начались внезапные трудности. ни по i2c, ни по spi, ни по uart модуль не определяется, не видится и только уныло светит диодом. В мониторе чаще всего что то типа "❌ PN532 not found via HSU!" или подобное. При поверхностном гуглеже ничего полезного не нашлось, копнув чуть глубже - нашел совет - юзать пин rstpdn. Не помогло никак, раз уж пишу. На ардуине, при этом, модуль работает как угодно - и по i2c, и по spi, и даже по hsu (uart). Обозначусь заранее - переключатели в правильном положении, напряжение тоже правильное, поступает куда надо, лампочка горит. Предлагать вернуться на ардуино - не стоит, я бы и сам сообразил. Три модуля esp, три модуля nfc (два синих, один красный V.3 от elechouse).
В оконцовке хрен в марганцовке на ардуине всё везде ништяк при любых раскладах, на есп - всё мертво как табуретка. Использовал библиотеки Adafruit_PN532, CIE-PN532, (NDEF, PN532, PN532_HSU, PN532_I2C, PN532_SPI - эти для elechouse вроде как раз)
Код на старте примерно такой:
#include <PN532_HSU.h>
#include <PN532.h>
// Указал пины для uart
#define PN532_RX 16 // Подключается к TX пинy PN532
#define PN532_TX 17 // Подключается к RX пинy PN532
#define PN532_RST 4 // Подключается к RSTPD_N на PN532
#define LED_BUILTIN 2 // Встроенный светодиод ESP32
// Вроде надо, что бы создать объекты для работы с библиотекой Elechouse
PN532_HSU pn532hsu(Serial2);
PN532 nfc(pn532hsu);
void setup() {
Serial.begin(115200);
 

Вложения

Старик Похабыч

★★★★★★★
14 Авг 2019
4,319
1,319
Москва
Надо по другому запускать сериал порт в esp
Для начала так HardwareSerial PN532 _com(2); // порт подключения весов
И потом инициировать его как обычно:
PN532 _com.begin(UART_SPEED, SERIAL_8N1, 17, 16);
Если сразу не пошло - поменять местами RX TX
 

Bruzzer

★★★★✩✩✩
23 Май 2020
679
206
@Старик Похабыч,
А в чем смысл этой манипуляции? У меня работает и просто
Serial2.begin(9600, SERIAL_8N1, 16, 17);
Собственно и Serial2.begin(9600); работает, просто ноги по умолчанию для Serial2 на обычной ESP32 это 4 и 25
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,319
1,319
Москва
1757141120493.png
Я смотрел с этой схемы, тут UART2 на 16, 17.
Пробовал разные конструкции, с простым запуском не заладилось, только в том виде, что я писал. Если что обмен данных с пром. весами типа Гулливер.
 

Bruzzer

★★★★✩✩✩
23 Май 2020
679
206
@Старик Похабыч,
Если не копаться в исходниках, то узнать (или проверить) назначенные по умолчанию пины можно
C++:
  Serial.begin(115200);
  Serial.println("Hello, ESP32!");

  Serial2.begin(9600);

  Serial.println(uart_get_RxPin(2));
  Serial.println(uart_get_TxPin(2));
Дополнение. Это справедливо для третьей версии адона. (Зачем они поменяли пины - не понятно).
Для второй версии пины по умолчанию 16 и 17, и функций uart_get_RxPin(2) uart_get_TxPin(2) не существует.
 
Изменено:
  • Лойс +1
Реакции: Старик Похабыч

314Zdec

✩✩✩✩✩✩✩
2 Сен 2025
2
0
Важное уточнение - на платах esp32c3 по uart все отлично соединяется и работает. НО! таки хотелось бы обычную esp и i2c Вот код
C++:
#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);
}