RFID Scanner + MQTT Probleme mit dem Code

Hallo ,
ich stoße bei meinem RFID-Projekt an meine Grenzen, da mir die Erfahrung und das wissen fehlt. Ich möchte per MQTT eine "1", "2" oder "3" an den D1 mini zurückgeben um damit den Buzzer zu steuern (Registrierte Karte = kurzes Signal, ungültige Karte = langes Signal).

Der RFID Code wird einwandfrei an den Mosquitto-Broker übermittelt. Allerdings empfängt der D1 mini keine Werte, die ich über den MQTT-Explorer an das Topic
( client.subscribe("SmartHome/RFID/Test")) publish.
Wenn ich den MQTT-Teil aus dem Programm isoliere und diesen in einem separatem Programm mit einem Buzzer betreibe funktioniert alles einwandfrei.
Was genau muss ich verändern, damit mein Code funktioniert.

Vielen Dank

#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>

#define SS_PIN D8
#define RST_PIN D1

#define BUZZER_PIN D2

MFRC522 mfrc522(SS_PIN, RST_PIN);
unsigned long cardId = 0;

WiFiClient net;
PubSubClient client(net);

const char* mqtt_server = "192.168.178.214";
const char* ssid = "*****";
const char* password = "******";

void setup() {
  Serial.begin(9600);
  SPI.begin();
  mfrc522.PCD_Init();

  pinMode(BUZZER_PIN, OUTPUT);

  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  digitalWrite(BUZZER_PIN, HIGH);
  delay(100);
  digitalWrite(BUZZER_PIN, LOW);
}

void reconnect() {
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
  }

  while (!client.connected()) {
    String clientId = "NodeMCUClient-";
    clientId += String(random(0xffff), HEX);
    client.subscribe("SmartHome/RFID/Test");

    if (!client.connect(clientId.c_str(), "****", "****")) {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");

      delay(5000);
    }
  }
}

void loop() {
  reconnect();

  if (!mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  if (!mfrc522.PICC_ReadCardSerial()) {
    return;
  }

  cardId = getCardId();

  Serial.print("New ");
  Serial.println(cardId);
  client.publish("SmartHome/RFID/Stop", "1");

  char buffer[10];
  sprintf(buffer, "%lu", cardId);
  client.publish("SmartHome/RFID/Code", buffer);

  digitalWrite(BUZZER_PIN, HIGH);
  delay(100);
  digitalWrite(BUZZER_PIN, LOW);

  uint8_t control = 0x00;

  do {
    control = 0;
    for (int i = 0; i < 3; i++) {
      if (!mfrc522.PICC_IsNewCardPresent()) {
        if (mfrc522.PICC_ReadCardSerial()) {
          control |= 0x16;
        }

        if (mfrc522.PICC_ReadCardSerial()) {
          control |= 0x16;
        }

        control += 0x1;
      }

      control += 0x4;
    }

    delay(1);
  } while (control == 13 || control == 14);

  reconnect();

  Serial.println("Removed");

  digitalWrite(BUZZER_PIN, HIGH);
  delay(300);
  digitalWrite(BUZZER_PIN, LOW);

  client.publish("SmartHome/RFID/Stop", "0");
  delay(500);
  
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
}

unsigned long getCardId() {
  byte readCard[4];
  for (int i = 0; i < 4; i++) {
    readCard[i] = mfrc522.uid.uidByte[i];
  }

  return (unsigned long)readCard[0] << 24
    | (unsigned long)readCard[1] << 16
    | (unsigned long)readCard[2] << 8
    | (unsigned long)readCard[3];
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if ((char)payload[0] == '1') {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(200);
    digitalWrite(BUZZER_PIN, LOW);   

  } if ((char)payload[0] == '2') {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(1000);
    digitalWrite(BUZZER_PIN, LOW);

  } if ((char)payload[0] == '3') {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(200);
    digitalWrite(BUZZER_PIN, LOW);
    delay(200);
    digitalWrite(BUZZER_PIN, HIGH);
    delay(200);
    digitalWrite(BUZZER_PIN, LOW);
  }
}
client.loop();

Fehlt im Loop

Vielen Dank für Deinen Tipp, allerdings lag es daran nicht. Vielleicht hat Du noch eine andere Idee.

Du lässt dir ja einige debug Ausgaben auf dem Serial Monitor ausgeben.

Was sagt den der Serial Monitor? Kommst du erfolgreich ins callback?

Dir ist schon bewusst, dass das Topic nur SmartHome/RFID/Test ist?

Du kannst dieses Topic im Explorer auch selbst abonnieren (oder eine Wildcard dahin) und selber auf deine Eingabe lauschen.

Ja, ist mir alles klar. Der RFID Code wird sowohl im Serial Monitor als auch im MQTT Explorer ausgegeben. Nur die "subscribe" Funktion funktioniert nicht. Lösche ich die Befehle, die für den RFID Scanner bestimmt sind funktionieren alle MQTT Funktionen.

Wird das erreichen der callback Funktion auf dem Serial Monitor ausgegeben?

  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");

Dieser Auszug aus deinem Code der callback Funktion sollte es auf dem Serial Monitor ausgeben.

Wenn dies nicht geschieht, ist das Topic nicht erfolgreich abonniert, oder die callback Funktion wird nicht erreicht.

Gern wird auch ein Schreibfehler eines führenden oder folgenden / im Topic gemacht.

Generell muss ein Topic neu abonniert werden, wenn der Client die Verbindung zum Server verliert.

Dein Code abonniert auch bei Fehlversuchen das Topic. Es wäre besser dies erst nach dem erfolgreichen Wiederverbinden zu tun.

Da du aber Topics mit Werten veröffentlichen kannst, scheint die Verbindung zu stehen.

Was ist das für eine Blockade?

while (control == 13 || control == 14);

Wenn dies nie verlassen wird, kommt dein Code nicht zur callback Funktion. Dein Code sollte nicht blockierend sein. Bzw. müsste client.loop(); in diese blockierende Schleife.

while (control == 13 || control == 14);

Diese Schleife prüft, ob eine RFID-Karte auf dem Scanner liegt meldet "Removed" an die Serial und eine "0" an das Topic "SmartHome/RFID/Stop". Das funktioniert auch prima.

Ich denke Deine These, dass die die callback Funktion wird nicht erreicht wird, trifft zu.
An welcher stelle genau muss ich den Befehl client.loop(); in meinem Code den platzieren. Ich habe bereits mehrere Stellen ausprobiert, allerdings ohne Erfolg.

Diese Funktion prüft auch ob Nachrichten auf den abonnierten Topics verfügbar sind und ruft wenn ja, die callback Funktion auf.

Sie sollte regelmäßig aufgerufen werden. Wenn man blockadefrei programmiert, reicht einmalig im loop()

Wenn es unbedingt blockierend sein soll, dann halt in der Blockade aufrufen. Der bessere Weg ist, die Blockade zu lösen.

Jetzt funktioniert alles :smile:!

ich habe die void reconnect() nochmal neu gebaut.

Hier der funktionierende Code:

#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>

#define SS_PIN D8
#define RST_PIN D1

#define BUZZER_PIN D2

MFRC522 mfrc522(SS_PIN, RST_PIN);
unsigned long cardId = 0;

WiFiClient net;
PubSubClient client(net);

const char* mqtt_server = "192.168.178.214";
const char* ssid = "Test";
const char* password = "*****";

void setup() {
  Serial.begin(9600);
  SPI.begin();
  mfrc522.PCD_Init();

  pinMode(BUZZER_PIN, OUTPUT);

  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  digitalWrite(BUZZER_PIN, HIGH);
  delay(100);
  digitalWrite(BUZZER_PIN, LOW);
}

void reconnect() {
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
  }

  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    String clientId = "WemosD1Client-";
    clientId += String(random(0xffff), HEX);

    if (client.connect(clientId.c_str(), "TestMQTT", "*****")) {
      client.subscribe("SmartHome/RFID/Test");
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");

      delay(5000);
    }
  }
}

void loop() {
  client.loop();
  reconnect();

  if (!mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  if (!mfrc522.PICC_ReadCardSerial()) {
    return;
  }

  cardId = getCardId();

  Serial.print("New ");
  Serial.println(cardId);
  client.publish("SmartHome/RFID/Stop", "1");

  char buffer[10];
  sprintf(buffer, "%lu", cardId);
  client.publish("SmartHome/RFID/Code", buffer);

  digitalWrite(BUZZER_PIN, HIGH);
  delay(100);
  digitalWrite(BUZZER_PIN, LOW);

  uint8_t control = 0x00;

  do {    
    control = 0;
    for (int i = 0; i < 3; i++) {

      if (!mfrc522.PICC_IsNewCardPresent()) {
        if (mfrc522.PICC_ReadCardSerial()) {
          control |= 0x16;
        }

        if (mfrc522.PICC_ReadCardSerial()) {
          control |= 0x16;
        }

        control += 0x1;
      }

      control += 0x4;
      client.loop();
    }

    delay(1);

  } while (control == 13 || control == 14);

  reconnect();

  Serial.println("Removed");

  digitalWrite(BUZZER_PIN, HIGH);
  delay(500);
  digitalWrite(BUZZER_PIN, LOW);

  client.publish("SmartHome/RFID/Stop", "0");
  delay(500);
  
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
}

unsigned long getCardId() {
  
  byte readCard[4];

  for (int i = 0; i < 4; i++) {
    readCard[i] = mfrc522.uid.uidByte[i];
  }

  return (unsigned long)readCard[0] << 24
    | (unsigned long)readCard[1] << 16
    | (unsigned long)readCard[2] << 8
    | (unsigned long)readCard[3];
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if ((char)payload[0] == '1') {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(200);
    digitalWrite(BUZZER_PIN, LOW);   

  } if ((char)payload[0] == '2') {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(1000);
    digitalWrite(BUZZER_PIN, LOW);

  } if ((char)payload[0] == '3') {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(200);
    digitalWrite(BUZZER_PIN, LOW);
    delay(200);
    digitalWrite(BUZZER_PIN, HIGH);
    delay(200);
    digitalWrite(BUZZER_PIN, LOW);
  }
}

Vielen Dank für Deine Unterstützung :+1:
Jetzt habe ich wieder etwas dazu gelernt :smiley:

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.