PN5180 and SSD1306 Project out of Memory

Hi all,

Please forgive my ignorance but I am still very new to this stuff. Conversely, please respond as if you're talking to a five year old so I can better understand.

Below is my current code and wiring diagram. I've successfully read some RFID cards with a serial print out (using a PN5180 module) and various associated LED activations. Separately, I've been able to get the SSD1306 screen to function and read out simple messages. The problem, to my understanding, is that when I want to do both, I am now out of memory. Apparently, the SDD1305 Adafruit library is the likely culprit. I attempted to perform the same tasks with the simpler U8G2 library but am at a loss for how to set it up. Previously, I've slowly adjusted example files to what I need with varied success.

End state for this project is to have a badge reader that signs out/in a workstation. User scans badge, turns LED from green to red, screen displays workstation #1234 is signed out on date/time and that date/time is logged. User scans badge again, turns LED from red to green, screen displays workstation #1234 is signed in on date/time, and that date/time is logged again.

I should add that I still want to add a RTC and process for storing date/times (probably quantity 10-20).

Any and all input greatly appreciated!


//card includes
#include <PN5180.h>
#include <PN5180ISO15693.h>

//*************************************************************************************


//screen includes
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>



//*************************************************************************************






#define PN5180_NSS  10
#define PN5180_BUSY 9
#define PN5180_RST  7



PN5180ISO15693 nfc(PN5180_NSS, PN5180_BUSY, PN5180_RST);



//*************************************************************************************



//screen defines
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);



//*************************************************************************************




//card and screen setup
void setup() {
  Serial.begin(115200);

  
  pinMode(4, OUTPUT);
  pinMode(2, OUTPUT);
  
  //4 is red
  //2 is green

 digitalWrite(2, HIGH);



  nfc.begin();

 
  nfc.reset();


  uint8_t productVersion[2];
  nfc.readEEprom(PRODUCT_VERSION, productVersion, sizeof(productVersion));


  if (0xff == productVersion[1]) { // if product version 255, the initialization failed
    Serial.flush();
    exit(-1); // halt
  }
  





  
  //****************screen setup
  
  
  
    // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }



  // Clear the buffer
  display.clearDisplay();

  display.display();
  delay(2000);

  testdrawstyles();    // Draw 'stylized' characters
  
  //*****************
}

uint32_t loopCnt = 0;
uint8_t numCard = 1;
const uint8_t maxTags = 16;
bool errorFlag = false;

//SLIX2 Passwords, first is manufacture standard
uint8_t standardpassword[] = {0x0F, 0x0F, 0x0F, 0x0F};
//New Password
uint8_t password[] = {0x12, 0x34, 0x56, 0x78};






//write screen
void testdrawstyles(void) {
  display.clearDisplay();

  display.setTextSize(2);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,0);             // Start at top-left corner
  display.println(F("WHERE'S"));
  display.setTextSize(2);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,17);             // Start at top-left corner
  display.println(F("THE BEEF!?"));
  
  
  display.display();
  delay(6000);
  
  display.clearDisplay();
  
  
  display.println(F(" "));
  display.display();
  
}





//*************************************************************************************



//card read
void loop() {


  // Multiple inventory
  Serial.println(F("----------------------------------"));
  Serial.print(F("Loop #"));
  Serial.println(loopCnt++);
  uint8_t uid[8*maxTags];
  ISO15693ErrorCode rc = nfc.getInventoryMultiple(uid, maxTags, &numCard);
  if (ISO15693_EC_OK != rc) {
    Serial.print(F("Error in getInventory: "));
    Serial.println(nfc.strerror(rc));
    errorFlag = true;
  }
  else if(!numCard){
    Serial.println("No cards detected.");
  }
  else{
    
    Serial.print("Inventory successful. Discovered ");
    Serial.print(numCard);
    Serial.println(" cards.");
    for(int i=0; i<numCard; i++){
      Serial.print("UID #");
      Serial.print(i);
      Serial.print("= ");
      for (int j=0; j<8; j++) {
        uint8_t startAddr = (i*8) + 7 - j;
        if(uid[startAddr] < 16) Serial.print("0");
        Serial.print(uid[startAddr], HEX); // LSB is first
        if (j < 2) Serial.print(":");
      }
      Serial.println();
    }
    
    //green to red
      if(digitalRead(2)==HIGH)
      {
       digitalWrite(2, LOW);
       digitalWrite(4, HIGH);
      }
      
    //red to green
      else
      {
       digitalWrite(2, HIGH);
       digitalWrite(4, LOW);
      }
    
  }
  Serial.println(F("----------------------------------"));
  
  

  
  delay(1000);
}



At first, without looking closely, you may get a win by stepping up to a controller with more memory, trying smaller fonts etc.

You’re using an R3, easy choice would be a MEGA.

What are the memory stats after compiling ?

The U8G2 is a better, lower memory choice, simple test program;


/*******************************************************************************************************
  Program Operation - This program is a simple test program for the SSD1306 and SH1106 OLEDs. The program
  prints a short message on each line, pauses, clears the screen, turns off the screen, waits a while and
  starts again.

  OLED address defaults to 0x3C.

  Screen write on 8Mhz Atmel 196mS.

  Serial monitor baud rate is set at 9600.
*******************************************************************************************************/

#include <U8x8lib.h>                                        //get library here >  https://github.com/olikraus/u8g2 
//U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE);    //use this line for standard 0.96" SSD1306
U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE);       //use this line for 1.3" OLED often sold as 1.3" SSD1306

#define DEFAULTFONT u8x8_font_chroma48medium8_r             //font for U8X8 Library


uint16_t writecount;
uint32_t startwritemS, endwritemS, timemS;


void loop()
{
  writecount++;
  Serial.print(writecount);
  Serial.print(F(" Writing to display"));

  startwritemS = millis();
  disp.clear();
  screen1();
  endwritemS = millis();
  timemS = endwritemS - startwritemS;
  disp.setCursor(8, 4);
  disp.print(timemS);
  disp.print(F("mS"));

  Serial.print(F(" - done "));
  Serial.print(timemS);
  Serial.println(F("mS"));

  delay(2000);
  Serial.println(F("PowerSave display"));
  Serial.flush();                                    //pending serial output affects sleep mode
  disp.setPowerSave(1);                              //power save display
  delay(5000);
  disp.setPowerSave(0);                              //display back to normal
}


void screen1()
{
  disp.setCursor(0, 0);
  disp.print(F("Hello World !"));
  disp.setCursor(0, 1);
  disp.print(F("Line 1"));
  disp.setCursor(0, 2);
  disp.print(F("Line 2"));
  disp.setCursor(0, 3);
  disp.print(F("Line 3"));
  disp.setCursor(0, 4);
  disp.print(F("Line 4"));
  disp.setCursor(0, 5);
  disp.print(F("Line 5"));
  disp.setCursor(0, 6);
  disp.print(F("Line 6"));
  disp.setCursor(0, 7);
  disp.print(F("0123456789012345"));                         //display is 8 lines x 16 charaters when using the
}


void setup()
{
  Serial.begin(9600);
  Serial.println(F("31_SSD1306_SH1106_OLED_Checker starting"));
  disp.begin();
  disp.setFont(DEFAULTFONT);
}

Can you post a link to where you got the PN5180 library?

If all you want to display on the SSD1306 OLED is text, there are some libraries that do not need a buffer for the display, such as SSD1306Ascii.

The Adafruit_SSD1306 library allocates a 1024 byte buffer at run-time, this does not show up in the memory usage shown by the compiler. If the out of memory error occurs at compile-time, then you will need a processor with more memory.

The U8g2 library can use either a full buffer (1024 bytes of ram), a paged buffer (much smaller amount of ram), or no buffer when using the u8x8 variation of the library. U8x8 is limited to text only, similar to the SSD1306Ascii library. Note that U8g2 allocates buffer space at compile-time, so it does show up in the compiler memory usage numbers.

2 Likes

While tempting, I'm trying to keep the unit as cheap as possible. If this one is successful, I'll need to duplicate it a few hundred times. If at all possible, I'd actually like to switch to a Nano down the road.

Memory stats are below:

I apologize if this is a dumb question but where in this test program are specific output pins identified? I seem to be at a loss in general on seeing where specific parts of the hardware is called out within the code. The only way I've gotten this far is when the github examples provide a wiring diagram.

I'll try and download this library and run the test program before reporting back.

See this thread where I struggled through getting that part of the project working:

I'm happy to try a different library with simple text output but my limitation is I'm dependent on example wiring diagrams to ensure physical wire locations match programming designations.

The SSD1306 is an I2C display, so you connect the SCL and SDA pins on the display to the SCL and SDA pins on your Arduino.

Which are what? Power and ground connections make sense to me but I currently have SCL going to A4 and SDA to A5. I only did so due to the example wiring diagram I previously found, don't see where that is assigned within my code.

Whilst there are some Arduino compatibles where you can assign the pins used by the I2C interface, in the majority of cases you dont need to 'assign' the pins at all.

So in the code I gave in #3 the display library will be starting up the I2C on the A4 and A5 pins, the code does not need to know that those are the pin numbers in use, they are fixed and the only pins the I2C interface can use. Why would specify something that is fixed ?

Thank you, this helped. I have it working now.

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