Uno + PN532 + NEOPIXEL + ESP8266 weird behaviour

Hello!

First of all I’m sorry if it’s the wrong forum section, I’m not sure what causes my problem!
It occurs when I try to run an Uno connected to a PN532 (NFC controller) to a Huzzah ESP8266 (Wifi board) and to a Neopixel strip (addressable LED strip).

Here is the simplified process of my project (corresponding to the code and pictures below): the ESP connects to the wifi, asks (through hardware serial) the Arduino data to connect to a MQTT server and subscribe to topics. Then the Arduino waits for a NFC tag detected by the PN532 then publish a MQTT message through the ESP and change the colour of the LED strip.

I tested the project with no USB connexion. The strip has its dedicated power supply (5V 3A), and the Uno is also powered through the barrel with its own power supply (9V 1A). The PN532 and the ESP are powered by the Arduino 3.3V and 5V.

The issue: when I power all the components at the same time, the ESP connects and exchanges with the Arduino but the PN532 does not detect any tag.

Where it’s starting to get strange is that I found several workarounds (after long hours trying to understand and reverting to working versions of the code) that make the project “works”:

  • Powering the Arduino after the other components (this solution is not visible in the pictures: the ESP has is connected to the strip power supply for that): then everything is working as expected! (but it’s not a solution for my project)
  • Removing the “strip.show()” in the loop() allows the PN532 to find tags again, and I really don’t know why…
  • Uncommenting an old code that I want to remove (with pointer array I don’t use anymore and debug logs, check the “old code” comment) and everything is working again, which don’t makes any sense to me ^^’
#include <SoftwareSerial.h>
#include <Adafruit_DotStar.h>
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>

//Use the softserial for debug
SoftwareSerial softSerial(10, 11);
bool debug = true;

//Serial buffer
char serialbuf[64]; 
const char SOPmarker = '<'; 
const char EOPmarker = '>'; 
#define MAX_STRING_LEN 64 

//Store MQTT topics and values
char *MQTT_topics[] = {"led/state", 
                      "switch/state", 
                      "switch/connected",
                      "neurotech/validuid",
                      "crystal1/validuid"};
char *MQTT_values[] = {"", "", "", "", ""}; //I'm trying to remove this ugly line...
int MQTT_topics_size;
byte index=0;

//State of the ESP8266
char espID = '2';
bool espReady = false;
unsigned long startESPMillis;

//PN532
#define PN532_SCK  (2)
#define PN532_MOSI (3)
#define PN532_SS   (4)
#define PN532_MISO (5)
Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);

//PN532 Timers
unsigned long startMillis;
unsigned long currentMillis;
int nfc_period = 1000;

//LED Strip
#define STRIP_PIN    13
#define STRIP_LED_COUNT 30
Adafruit_NeoPixel strip(STRIP_LED_COUNT, STRIP_PIN, NEO_GRB + NEO_KHZ800);


void setup() {
  
  Serial.begin(9600);
  softSerial.begin(9600);

  if (debug) {
    softSerial.println("Running on the Arduino");
  }

  //Compute MQTT_topics sizee -- trying to remove that to
  MQTT_topics_size = sizeof(MQTT_topics) / sizeof(MQTT_topics[0]);
  
  //PN532

  nfc.begin();

  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    softSerial.print("Didn't find PN53x board");
    while (1); // halt
  }
  // Got ok data, print it out!
  softSerial.print("Found chip PN5");

  nfc.setPassiveActivationRetries(1);
  
  // configure board to read RFID tags
  nfc.SAMConfig();
  
  softSerial.println("Waiting for an ISO14443A Card ...");

  //LED Strip
  
  strip.begin();   
  strip.fill(strip.Color(243,77,9));
  strip.setBrightness(50);
  strip.show();
}

void loop() { 

  //ESP => Arduino serial reception
  if (Serial.available()) {
    
    static int bufpos = 0; 
    char inchar = Serial.read();
    
    if (inchar != EOPmarker && inchar != SOPmarker) { 
      serialbuf[bufpos] = inchar; 
      bufpos++;
      
    }else if (inchar == SOPmarker) { 
      bufpos = 0;
    
    }else{
      //Package received
      serialbuf[bufpos] = 0; 
      bufpos = 0;

      if (debug) {
        softSerial.print("received: ");
        softSerial.println(serialbuf);
      }

      //Split the package into header and content
      char* header = subStr(serialbuf, "!", 1);
      char* content =  subStr(serialbuf, "!", 2);
      
      if(strcmp(header, "ESP") == 0) {
        //Received a request to id the ESP
        if (debug) {
          softSerial.print("sent: ");
          softSerial.println("<ESP!1>");
        }
        
        Serial.print("<ESP!");
        Serial.print(espID);
        Serial.print(">");
          
      }else if(strcmp(header, "TOPIC") == 0) {
        //Received a request to get the topic to subscribe
        long index = atol(content);

        if(index < MQTT_topics_size) {
          char message[] = "<TOPIC!";
          strcat(message,MQTT_topics[index]);
          strcat(message,">");

          if (debug) {
            softSerial.print("sent: ");
            softSerial.println(message);
          }
          
          Serial.print(message);
        }else{
          // No more topic to subscribe, stop the request loop
          if (debug) {
            softSerial.print("sent: ");
            softSerial.println("<TOPIC!STOP>");
          }
          
          Serial.print("<TOPIC!STOP>");
        }
      }else if(strcmp(header, "READY") == 0) {
        //receive that ESP is ready to receive
          
        espReady = true;
        
      }else{
        //No specific header = topic update
        
        //==> Old code I'm trying to remove! <==
        /*
        for (int i = 0; i < MQTT_topics_size; i++) {
          if(strcmp(header, MQTT_topics[i]) == 0) {
            MQTT_values[i] = content;
          }
          
          if (debug) {
            softSerial.println(MQTT_values[i]);
          }
        }
        */
        //==> End of old code I'm trying to remove! <==

        //Confirm the reception
        Serial.print("<CHECK!0>"); 

        //Check the Crystal status
        if(strcmp(serialbuf, "crystal1/validuid!powertrue") == 0){
          
          //Color the strip
          strip.fill(strip.Color(243,77,9));
          strip.show(); //==> Comment this and it's working! <==
          
          //Publish opening
          Serial.print("<crystal1/state!yes");
         
        }
      }
    }
  }
  
  currentMillis = millis(); 
  
  if(espReady){

    //Every second, check for NFC tag
    if (currentMillis - startMillis >= nfc_period)  
    {
  
      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.print("<neurotech/scanuid!TEST>");
      }
      
      startMillis = currentMillis;  
    }
  }else{

    //If ESP is still not ready, restart configuration
    if (currentMillis - startESPMillis >= 3000){
      Serial.print("<ESP!");
      Serial.print(espID);
      Serial.print(">");
      
      startESPMillis = currentMillis; 
    }
  }
}

char* subStr (char* input_string, char *separator, int segment_number) {
  char *act, *sub, *ptr;
  static char copy[MAX_STRING_LEN];
  int i;
  strcpy(copy, input_string);
  for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {
    sub = strtok_r(act, separator, &ptr);
    if (sub == NULL) break;
  }
  return sub;
}

Sorry for the long code, I tried to remove as much as possible but as I’m not sure where the issue is, I preferred to keep a good part of it.

I could also publish my ESP8266 code if you think it’s useful (but it is working well with different projects), or anything else… (Sorry for the mess on the pictures especially around the PN532, it is welded like this for a previous project but works well with basic codes).

So if you have an idea to explain this weird behaviour that seems (to me) to connect unrelated things, i’m interested!! Thanks for taking the time to read my issue :slight_smile:

Mysterarts: the Uno is also powered through the barrel with its own power supply (9V 1A). The PN532 and the ESP are powered by the Arduino 3.3V and 5V.

That may be your problem, the Uno uses a small, linear voltage regulator to regulate 9V to 5V/3.3V. The ESP consumes roughly about 150mA (depending on the usage) and this means that the VRM's on the Arduino has to dissipate ((9V-3.3V) * 0.150A) 855mW of heat. That is a lot (as in too much!) for small SMD regulators!

Maximum current draw from 3.3V is 50mA!

Hi Danois90, thanks for your answer :slight_smile:

I didn’t know that the VRM dissipation was calculate like that (even if the ESP uses the 5V?), thanks for the explanation!
I tried to connect the ESP to the strip power supply and you are right, everything is working fine :o
[EDIT: no it’s not :frowning: see https://forum.arduino.cc/index.php?topic=645838.msg4369206#msg4369206]

However in the complete project (with several other components connected to the strip power supply but also a LED to the Arduino 5V), I was powering the ESP with it’s own power supply (connected to the other GND) and the issue was still here, it’s weird…

I will rebuild the complete projet to see if I can only power the PN532 with the arduino and see if the issue is resolved!

A question by the way (very basic I’m afraid): if there are a lot of components on the same power supply and I see on my voltmeter that some components don’t get the complete 5V, it’s because a too high resistance / not enough ampere? I should find a higher amp power supply? Or it’s something else? Sorry again for the noob question…

Mysterarts: if there are a lot of components on the same power supply and I see on my voltmeter that some components don't get the complete 5V, it's because a too high resistance / not enough ampere? I should find a higher amp power supply?

If the wire is too long and/or too thin it's resistance will cause the voltage to drop. If you overload the power supply it may drop in voltage or cut off due to overheating. If it is a poor quality power supply it may even start to smolder and in worst case even catch fire! Be carefull not to overload your PSU's!

By « overload » you mean asking for too much watts, right? My wires are quite shorts, but I need to check the diameters. Is increasing the amp of the PSU prevent the overload? (But I suppose I need to try to reduce the resistance first).

Thanks again for your quick answers :)

Mysterarts: My wires are quite shorts.

I would not wear them, though.... :-P

By overload I mean that you draw more current than the supply is rated for, here you should also mind any voltage regulation (as on the Arduino etc). Whenever you design a gizmo, you should be very thorough with the power delivery since this is what feeds it. Use as few quality PSU's as possible and always have a current overhead.

Danois90: I would not wear them, though.... :-P

Aha :p As you may have guessed, English is not my native language ;) (Basic electricity knowledge neither ^^).

To be sure: by current overhead you mean like a margin in the amp calculation?

I must admit I always used a small number of components at the same time until now and simply used the recommended PSU. It’s more complicated with several components! I can sum the amp but for the resistance it’s more abstract for me for example...

I unfortunately claimed victory too quickly! I did the first test mentioned above in a hurry yesterday and I thought it worked but today I can't reproduce it, my problem is still there :'(

I tried to power the ESP with the LED strip's power supply, then with its own PSU, but it changes nothing. I tried to power the PN532 with the 5v (but always with the 9v barrel power supply on the Uno) and then with the LED strip's PSU, with the same result... I tried to add a 100uF capacitor between the PN532's 5V and GND pins, and one between the ESP8266's Vin and GND pins, still no result.

And for every tests, I tried to simply removed the "old code" lines and everything worked, which I really have a hard time understanding! How this code could help ^^'? I tried to replace it by a delay without success.

Do you have another idea to test? Thanks in advance :)

Do you have some sort of logic level shifter in between of the Arduino and the ESP? Arduino uses 5V logic and the ESP uses 3.3V and this could be a problem.

If I’m not mistaken, the HUZZAH board provides a level shifter on the RX pins: Pinouts | Adafruit HUZZAH ESP8266 breakout | Adafruit Learning System
And as the TX pin is only an output, it should work, right?
Except in this problematic situation, this setup (Uno <=> ESP) seems to be fairly stable…
In fact even here, the connection of the ESP works well, I feel like it’s mostly the PN532 that doesn’t respond anymore (but eh, it’s not that simple, right ^^’)

Thanks again for your suggestions!

Sorry for the late reply! According to this spec sheet, the NFC module may consume a whopping 140mA - this is again a lot of power to be drawn from the 5V pin of the Arduino when it is supplied with 9V.

Again you must consider how a linear regulator works. It is basically a dynamic resistor which will convert the voltage difference into heat. A larger difference in voltage is thus harder to handle than a smaller difference. Look at these calculations for a 140mA@5V attachment:

12V input: (12V - 5V) * 0.14 = 0.98 watt. 9V input: (9V - 5V) * 0.14 = 0.56 watt. 6V input: (6V - 5V) * 0.14 = 0.14 watt. 5V input: (5V - 5V) * 0.14 = 0 watt.

Even if the Arduino is capable of using a 12V power supply, the high input voltage limits how much current it is able to supply at 5V due to its small VRM, and that is why picking the right power supply is important. Good luck! :-)

Thanks Danois90 for the details of the calculations :)

I don't have a 6V power supply here. But I tried to give to each component (PN532, Strip, ESP and Uno) its own PSU. I don't know if it even makes sense ^^' I connected the GND all together. So the Uno is not powering anything now, and it's still not working (except by removing the old code as always). Can we conclude that the PSU of the Uno is not responsible of the issue?

But I discovered that if I stop all the PSU at the same time and turn them back on before the POWER LED of the PN532 goes out (for some reason it takes 3sec time to stop, even when I've removed my own capacitors in the circuit, probably capacitors on the boards?), well this time I have all the components that work and thus the PN532 capturing my TAGs etc.

Does it help to understand what the problem might be?

Mysterarts: So the Uno is not powering anything now, and it's still not working (except by removing the old code as always). Can we conclude that the PSU of the Uno is not responsible of the issue?

But I discovered that if I stop all the PSU at the same time and turn them back on before the POWER LED of the PN532 goes out (for some reason it takes 3sec time to stop, even when I've removed my own capacitors in the circuit, probably capacitors on the boards?), well this time I have all the components that work and thus the PN532 capturing my TAGs etc.

Does it help to understand what the problem might be?

In your original post, it only worked with the old code, now it only works without? We cannot conclude anything since it is not working as expected yet.. Yes, there might be capacitors on the PN532 keeping it powered for the 3 seconds after the power is cut.

What happens if you power on the PN532 a couple of seconds before all the other components?

Danois90: In your original post, it only worked with the old code, now it only works without?

Sorry, I meant it only worked by keeping the old code ^^'

So I tried to power the PN532 1sec, 2sec, 3sec, 10sec before all the other components, with no success. (I also tried to power the Uno after the others with no success, but as in previous tests, if I power everything then unplug / plug the Uno, it works !)

Thank you very much for continuing to investigate with me!

Removing the "strip.show()" in the loop() allows the PN532 to find tags again, and I really don't know why...

i couldn't find exactly where it is (so confirming for how much time this is happening is a little tricky) , but during .show() interrupts get turned off, and that may have something to do with it.

Thanks Deva_Rishi for this information!

It's not easy to point a line in the code on this forum but it's line 186 (a ctrl+F on the page should show it to you). But this part of the code is theoretically only triggered after a first tag detection... Which makes it even weirder for me that removing it allows the detection to work ^^'

Actually, why are you using, or what are you using, the UNO for that can not be done by the HUZZAH ? You see i was going to suggest you connect the PN532 using the UART rather than SPI, but then i realized that the HUZZAH is using that, though that could be moved to swSerial, which works reliably enough at that speed (though i haven't checked the code) then i considered letting the ESP take care of the LED-strip, but for the WIFI to work properly it needs to be done in DMA-mode using Makuna -Neopixelbus library which uses the UART RX pin as the data pin, so then the UART is not available then i figured, what is the UNO really doing in the project at all ? The HUZZAH has SPI, the LEDS can be controlled, and it's plenty quick to do all task required.

It's not easy to point a line in the code on this forum but it's line 186

well it is somewhere in loop(), but loop() is really huge, Putting some of the code in functions would greatly improve the overview.

Well I’m using an Arduino because in the complete project, I have a lot of inputs and outputs to manage with it :wink:

But I must admit that I was also not sure if the HUZZAH (except for the problem of the pin number, which could perhaps be solved) was able to drive the LED strip or the PN532 ^^

I could try other interfaces to communicate with the PN532. I tried using swSerial on the ESP and it seems less reliable at the time (It was maybe because of something else). Maybe using I2C between Uno and PN532?

And yes you’re right, I need to organise my code with fonctions ^^’

Thanks for your suggestions :slight_smile:

But I must admit that I was also not sure if the HUZZAH (except for the problem of the pin number, which could perhaps be solved) was able to drive the LED strip or the PN532 ^^

Neither was i, but it is plenty quick and supports SPI, and driving LED's i do a lot with ESP's but there are issues with bit-banged icw WIFI, but DMA (or UART) will work just fine, the PIN nr, can't be changed though (GPIO3 for DMS & GPIO1 for UART mode)

I tried using swSerial on the ESP and it seems less reliable at the time

it is a lot less reliable for sure icw LED-strip. I Have projects where i connect an ESP to an Arduino, but simply because i want to receive DMX and the BAUD-rate required is not supported by the ESP, which with i then have to communicate over swSerial, so it is a little less reliable, but with pinging by the Arduino for an answer from the ESP makes it more reliable. Anyway you have plenty to do and try.