element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
NFC/RFID
  • Challenges & Projects
  • Project14
  • NFC/RFID
  • More
  • Cancel
NFC/RFID
Blog NFC-Badge - Update your badge with your smartphone - improvements
  • Blog
  • Forum
  • Documents
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join NFC/RFID to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: bernhardmayer
  • Date Created: 18 Jun 2019 12:40 AM Date Created
  • Views 2042 views
  • Likes 6 likes
  • Comments 0 comments
  • nfc ndef
  • nfcrfidch
  • nfc type 5 tag
  • badge
  • nfc tag
Related
Recommended

NFC-Badge - Update your badge with your smartphone - improvements

bernhardmayer
bernhardmayer
18 Jun 2019

Today I want to give an update on my NFC badge with some improved functions. Unfortunately the code and the video are of low quality as this is work in progress.

 

In my last blog post (NFC-Badge - Update your badge with your smartphone - NDEF and app ) I described how the data is formatted on the eeprom. So I wrote some code which decodes this data. It checks if there is valid NDEF data on the eeprom and then goes down through all the NDEF messages and recordings. When it finds a text record it displays the content on the display. If no text record is found it displays an error. If there are other NDEF records like for example URI records on the eeprom they are ignored.

 

Additionally I connected the busy pin of the M24LR to pin 12 of the Arduino Uno just like on the X-NUCLEO-NFC02A1. Now the Arduino is able to detect if the content of the eeprom was updated and redraw the display. So no reboot is necessary anymore.

 

Another small improvement is the centering of the name on the display. Dependent on the length of the string the position is calculated.

 

Below is a video (bad quality, sorry) which shows how a smart phone is connected to the badge. The phone uses the ST25 NFC Tap app. The NDEF text record is deleted and then generated again and changed. The display is updated each time accordingly. After the phone is removed the last content stays on the display. You can see how the display blinks regularly. This is due to changes on the busy pin. So I suppose the phone accesses the tag in regular time periods.

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

Here is the code (bad documentation):

 

#include <Wire.h> // i2c-lib
#include <dog_7565R.h>
#include "font2.h"
#include "font.h"

#define M24LR_BUSY 12    // M24LR busy pin

dog_7565R DOG;

byte backlight=255;
int led       = 10;
void init_backlight(boolean mono);
void mono_backlight(byte brightness);

bool is_valid_tag = false;
int tag_pointer=0;
int record_pointer=0;

//create badge sceen content
void badge_screen(char *x, int xlen)
{
  int font_width=0;
  int font_start=0;
  font_width=font2[4];
  font_start=64-(font_width*xlen/2);
  if(font_start<0) font_start=0;

  Serial.print("font width: ");
  Serial.println(font_width);
  Serial.print("font start: ");
  Serial.println(font_start);
  DOG.clear();  //clear whole display
  DOG.string(25,0,font2,"Hello");
  DOG.string(22,3,font,"my name is");
  DOG.string(font_start,5,font2,x);
}

//create error content
void error_screen(char *x)
{
  DOG.clear();  //clear whole display
  DOG.string(25,1,font2,"Error");
  DOG.string(0,5,font,x);
}

//read byte from eeprom with 16 register
unsigned char i2c_read_byte(char address, unsigned short reg)
{
  char x=0;
  Wire.beginTransmission(address);
  Wire.write((reg&0xff00)>>8);
  Wire.write(reg&0x00ff);
  Wire.endTransmission();
  Wire.requestFrom(address,1);
  if(Wire.available()) x=Wire.read();
  Wire.endTransmission();
  return x;
}

bool check_valid_tag(void)
{
  if(i2c_read_byte(0x53,0)==0xE1) is_valid_tag=true;  // check NDEF magic number 0xE1
  else is_valid_tag=false;
  return is_valid_tag;
}

int memory_length(void)
{
  if(is_valid_tag) return (i2c_read_byte(0x53,2)*8);
  else return -1;
}

int find_next_ndef_message(void)
{
  char byte_buffer=0;
  int message_length=0;
  if(!is_valid_tag) return -1;  // exit if no valid tag
  if(tag_pointer==0) tag_pointer=4; // skip cc block
  do
  {
    byte_buffer=i2c_read_byte(0x53,tag_pointer);
    if(byte_buffer==3)  // found next NDEF message
    {
      message_length=i2c_read_byte(0x53,tag_pointer+1);
      record_pointer=tag_pointer+2; // set record_pointer to beginning of first record
      tag_pointer=tag_pointer+2+message_length;  // set tag pointer to beginning of next ndef message
      return message_length;
    }
    if(byte_buffer==0xFE)  // found Terminator
    {
      return -1;
    }
    byte_buffer++;
  } while(byte_buffer==0);  // read all null bytes
  return -1;  // something went wrong
}

unsigned char get_record_tnf(void)
{
  return (i2c_read_byte(0x53,record_pointer)&0x07);
}

unsigned char get_record_type(void)
{
  return i2c_read_byte(0x53,record_pointer+3);
}

int get_record_length(void)
{
  return i2c_read_byte(0x53,record_pointer+2);
}

int find_next_record(void)
{
  unsigned char record_header=0;
  record_header=i2c_read_byte(0x53,record_pointer);
  if(record_header&0x40) return -1;   // check ME bit
  else record_pointer+=(get_record_length()+4);
  return record_pointer;
}

//decode string from ndef file and tag and return buffer and length
int get_record_language_code(char* string_buffer)
{
  int language_code_length=0,i=0;

  language_code_length=(i2c_read_byte(0x53,record_pointer+4)&0x1F);

  for(i=0;i<language_code_length;i++)
  {
    *string_buffer=i2c_read_byte(0x53,record_pointer+5+i);  // text starts at offset 10 bytes from the beginning
    string_buffer++;
  }
  *string_buffer=0;
  return language_code_length;
}
//decode string from ndef file and tag and return buffer and length
int get_record_text_string(char* string_buffer)
{
  int record_length=0, i=0;
  int language_code_length=0;

  language_code_length=(i2c_read_byte(0x53,record_pointer+4)&0x1F);
  record_length=get_record_length();

  for(i=language_code_length+1;i<record_length;i++)
  {
    *string_buffer=i2c_read_byte(0x53,record_pointer+4+i);  // text starts at offset 10 bytes from the beginnig
    string_buffer++;
  }
  *string_buffer=0;
  return (record_length-language_code_length-1);
}

void check_ndef_tag()
{
  char nfc_string[20];  // buffer for text string
  int string_length=0;
  int record_tnf=0;
  int found_text_record=0;
  tag_pointer=0;
  record_pointer=0;
  if(!check_valid_tag()) error_screen("no valid NDEF tag");  // check if tag is valid
  else 
  {
    Serial.print("NDEF memory length:  ");
    Serial.println(memory_length());
    Serial.print("NDEF message length: ");
    Serial.println(find_next_ndef_message());
    Serial.print("Record pointer: ");
    Serial.println(record_pointer);
    do
    {
      Serial.print("Record pointer: ");
      Serial.println(record_pointer);
      record_tnf=get_record_tnf();
      Serial.print("Record tnf:    ");
      Serial.println(record_tnf,HEX);
      if(record_tnf==1)   // Well-Known Record
      {
        Serial.print("Record type:   ");
        Serial.println(get_record_type(),HEX);
        Serial.print("Record length: ");
        Serial.println(get_record_length());
        if(get_record_type()==0x54)   // found text record
        {
          get_record_language_code(nfc_string); // get string from eeprom
          Serial.print("language_code: ");
          Serial.println(nfc_string); // print string on serial
          string_length=get_record_text_string(nfc_string); // get string from eeprom
          Serial.print("text string:   ");
          Serial.println(nfc_string); // print string on serial
          Serial.print("text length:   ");
          Serial.println(string_length); // print string on serial
          badge_screen(nfc_string,string_length);        //show content
          found_text_record=1;
          break;    // break after first text record
        }
      }
    } while(find_next_record()>0); // go through all records
    if(found_text_record==0) error_screen("found no text record");        //show error
  }
}

void setup() {
  // put your setup code here, to run once:
  byte error,address,x;
  int nDevices;

  pinMode(M24LR_BUSY, INPUT_PULLUP);    // M24LR busy pin

  Serial.begin(115200); // setup serial
  Wire.begin(); // setup I2C
  Wire.setClock(1000);
  delay(10);

// scan for I2C devices
  Serial.println("Scanning I2C...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }


  Serial.println("Init Display");
  init_backlight(true); //use monochrome backlight in this sample code. Please change it to your configuration
  DOG.initialize(6,5,7,8,9,DOGM128);   //SS = 10, 0,0= use Hardware SPI, 9 = A0, 4 = RESET, EA DOGM128-6 (=128x64 dots)
  DOG.clear();  //clear whole display
  mono_backlight(255);    //BL to full brightness
  DOG.view(VIEW_BOTTOM);  //default viewing direction

  check_ndef_tag();
}

void loop() {
  // put your main code here, to run repeatedly:
  static int trigger_input_old=HIGH;
  int trigger_input=HIGH;

  trigger_input=digitalRead(M24LR_BUSY);
  if((trigger_input_old==LOW)&&(trigger_input==HIGH)) 
  {
    delay(500);     // wait a little bit until write is complete
    check_ndef_tag();  // check ndef tag at etch of busy signal
  }
  trigger_input_old=trigger_input;
  delay(10);
}

//The following functions controll the backlight with a PWM. Not needed for the display content
void init_backlight(boolean mono)
{
  if(mono) //EA LED55X31-G, EA LED55X31-W, EA LED55X31-B, EA LED55X31-A, EA LED55X31-R
  {
    pinMode(led,  OUTPUT);
    mono_backlight(255);
  }
}
//Use this funtion for monochrome backlight
void mono_backlight(byte brightness)
{
  analogWrite(led, brightness);  
}

 

What's next

 

rewrite the code and do some more testing. And maybe a better video.

  • Sign in to reply
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube