Using NFC tags to change RGB LED colours

I document my experiment code here. So I will find it next time when I need it.

Code

/*
  Copyright 2023 Tauno Erik
  Started: 07.10.2023
  RC522 module
 */
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>
#include <Adafruit_NeoPixel.h>

// pins for SPI communication.
#define PN532_SCK    SCK
#define PN532_MOSI   MOSI
#define PN532_SS     SS
#define PN532_MISO   MISO
#define PN532_IRQ    22
#define PN532_RESET  21

Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);

const int RGB_PIN = 2;
const int NUMPIXELS = 6;
Adafruit_NeoPixel pixels(NUMPIXELS, RGB_PIN, NEO_GRB + NEO_KHZ800);

int counter = 0;
uint8_t green_tag[7] = { 0x1D, 0xDE, 0xBC, 0xDC, 0x93, 0x00, 0x00 };
uint8_t   red_tag[7] = { 0x1D, 0x26, 0xBD, 0xDC, 0x93, 0x00, 0x00 };

const uint32_t OFF = pixels.Color(0, 0, 0);
const uint32_t GREEN = pixels.Color(0, 150, 0);
const uint32_t BLUE = pixels.Color(0, 0, 150);
const uint32_t RED = pixels.Color(150, 0, 0);

uint32_t pixels_colors[NUMPIXELS] = {OFF};

/*
Compare the two arrays
*/
bool is_equal(uint8_t array1[], uint8_t array2[]) {
  bool result = true;

  for (uint8_t i = 0; i < sizeof(array1); i++) {
    if (array1[i] != array2[i]) {
      result = false;
      break;
    }
  }
  return result;
}

void add_color(uint32_t new_color) {
  // move elemnts to right one step
  for (int i = NUMPIXELS; i > 0; i--) {
    pixels_colors[i] = pixels_colors[i-1];
  }
  pixels_colors[0] = new_color;
}

void setup(void) {
  Serial.begin(115200);
  /*
  while (!Serial) {
    delay(10);
  }
  */
  Serial.println("Hello!");

  pixels.begin();
  pixels.show();             // Turn OFF all pixels ASAP
  pixels.setBrightness(50);  // Set BRIGHTNESS to about 1/5 (max = 255)

  nfc.begin();

  uint32_t versiondata = nfc.getFirmwareVersion();

  if (!versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1) {
      // halt
    }
  }

  // Got ok data, print it out!
  Serial.print("Found chip PN5");
  Serial.println((versiondata>>24) & 0xFF, HEX);
  Serial.print("Firmware ver. ");
  Serial.print((versiondata>>16) & 0xFF, DEC);
  Serial.print('.');
  Serial.println((versiondata>>8) & 0xFF, DEC);

  // Set the max number of retry attempts to read from a card
  // This prevents us from waiting forever for a card, which is
  // the default behaviour of the PN532.
  nfc.setPassiveActivationRetries(0xFF);

  Serial.println("Waiting for an ISO14443A card");
}

void loop(void) {
  pixels.clear();  // Set all pixel colors to 'off'
  boolean success;

  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  // 4 or 7 bytes depending on ISO14443A card type
  // ntag 7 bytes
  uint8_t uid_length;

  // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
  // 'uid' will be populated with the UID, and uidLength will indicate
  // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uid_length);

  if (counter > NUMPIXELS) {
    counter = 0;
  }

  if (success) {
    Serial.println("Found a card!");
    Serial.print("UID Length: ");
    Serial.print(uid_length, DEC);
    Serial.println(" bytes");

    Serial.print("UID Value: ");
    for (uint8_t i=0; i < uid_length; i++) {
      Serial.print(" 0x");
      Serial.print(uid[i], HEX);
    }
    Serial.println("");

    if (is_equal(green_tag, uid) && uid_length == 7) {
      Serial.println("green tag");
      add_color(GREEN);
    } else if (is_equal(red_tag, uid) && uid_length == 7) {
      Serial.println("red tag");
      add_color(RED);
    } else {
      Serial.println("unknown tag");
      add_color(OFF);
    }


    counter++;
    for (int i = 0; i < NUMPIXELS; i++) {
      pixels.setPixelColor(i, pixels_colors[i]);
    }
    pixels.show();
    delay(500);  // slowdown

  } else {
    // PN532 probably timed out waiting for a card
    // Serial.println("Timed out waiting for a card");
    Serial.println("---");
  }
}

Demos:

Links:

Notes about Arduino RFID readers

I bought some RFID readers and plan to experiment with them soon. Here are my notes.

RDM6300

  • Working frequency: 125 KHz
  • Reads EM4100 compatible tags
  • Interface: UART, Baud rate 9600
  • Read Range 20-50 mm
  • Operating voltage: 5V DC

Arduino libraries:

RFID-RC522, Mini RFID-RC522

  • Working frequency: 13.56 MHz, ISM Band
  • ISO 14443A standard tags. Supports Mifare1 S50, Mifare1 S70, Mifare Light, Mifare UltraLight and Mifare Pro, Mifare Desfire.
  • Interfaces: SPI 10Mbps, I2C, UART
  • Operating voltage: 3.3 V (Logic pins are 5V tolerant)
  • Read Range – 50 mm

Can be programmed to generate an interrupt (IRQ), allowing the module to alert us when a tag approaches it.

Arduino libraries:

Connecting Raspberry Pi Pico

RS522 pinPi Pico pin
MISOGPIO16
SSGPIO17
SCKGPIO18
MOSIGPIO19
3.3V3.3V
GNDGND

Dump info examples:

NFC module V3 PN532

  • 13.56 MHz
  • Interfaces: I2C, SPI, HSU (High-Speed UART)
  • Mifare cards 1k, 4k, Ultralight and DesFire ISO / IEC 14443-4 cards such as CD97BX, CD light, Desfire, P5CN072 (SMX) Innovision Jewel Cards as IRT5001 card. FeliCa cards such as RCS_860 and RCS_854. P2P communication with peers, NFC with Android phone
  • On-board level shifter, Standard 5V TTL for I2C and UART, 3.3V TTL SPI
  • Read Range 50-70 mm

Arduino libraries:

MIFARE Classic 1K Memory Layout

The tag’s 1K memory is organized into 16 sectors (from 0 to 15).

Each sector is divided into 4 blocks (blocks 0 to 3).

Each block can store 16 bytes of data (from 0 to 15).

The last block of each sector is called a Sector Trailer. It contains information called Access Bits that provide read and write access to the remaining blocks in the sector. This means that only 3 blocks of each sector (Blocks #0, #1 and #2) are actually writable, in other words only 48 bytes per sector are available for use.

Block #0 of Sector #0 is called Manufacturer Block which contains IC Manufacturer data and a Unique Identifier (UID).

Links

Seeed mmWave radar sensor

In one project I needed to use Seeed Studio mmWave radar MR24HPC1, and to better understand how it works and what it does, I ended up writing my own Arduino library for this sensor. Learned a lot.

It has two modes: simple and advanced.

Available methodsSIMPLEADVANDCED
reset()++
get_mode()++
get_heartbeat()++
get_activity()+
get_direction()+
get_motion()+
get_presence()+
get_motion_energy()+
get_motion_speed()+
get_motion_distance()+
get_static_energy()+
get_static_distance()+
get_initialization_status()+
get_time_for_entering_no_person_state()++
get_motion_trigger_time()+
get_motion_to_static_time+
get_static_trigger_limit()+
set_static_limit()+
set_motion_limit()+
set_static_threshold+
set_motion_threshold+
set_absence_trigger_time+

My Arduino library for Seeed MR24HPC1 24GHz radar is in GitHub.

NFC ja NTAGid

NFC

Near Field Communication ehk lähiväljaside on juhtmevabade tehnoloogiate kogum, mis nõuab ühenduse loomiseks 4 cm või väiksemat vahemaad. NFC võimaldab jagada andmeid NFC-sildi ja telefoni või kahe mobiiltelefoni vahel.

Töötamiseks peavad olemad NFC-sildi ja telefoni antennid lähestikku, et tekkiks vastastikune induksioon. Kus voolumuutus aktiivses seadmes (mobiil telefon) kutsub esile elektromootoorjõu passiivses seadmes (NFC-silt).

NFC-märgised võivad olla erineva kompleksusega. Lihtsamad võimaldavad lugemist ja kirjutamist. Keerulisemad pakuvad matemaatilisi toiminguid ja krüptograafilist riistvara. Kõige keerulisemad võivad käituda peaaegu nagu väiksed arvutid.

Andmed NFC sildil võivad olla kirjutatud erinevas vormingus aga kõige levinum on NFC Forumi poolt arendatud standard NDEF (NFC Data Exchange Format).

NFC tööpõhimõte

NTAG

NTAG® on NXP ® pool välja arendatud NFC märgised, tegelikult märgise sees olevad kiibid, mis on mõeldud laiaotstabelisteks tavatarbija kasutamiseks: jaemüügis, mängudes, tarbeelektroonikas, trükimeedia nutikad reklaamid, toodete autentimine, riiulisildid, visiitkaardid, WiFi sidumiseks jne. Töötavad kõikide telefonidega, kus on NFC olemas. Kiibi paksus on 75 μm. Ühe kleebise paksus on u 0.27 millimeetri. Märgisel olevat sisu (andmeid) saab korduvalt muuta ja ülekirjutada. Võimalusel saab lisada kirjutuskaitse, pärast mida andmeid enam ei saa muuta. Märgistel puudub oma energia allikas (patarei). Energia kantakse kiibi lugemise käigus üle raadiolainete kaudu (sagedusel 13,56 MHz). Töökaugus sõltub väljatugevusest ja antenni suurusest/kujust. Saab lisada paroolikaitse (NTAG 215 ja NTAG 216).

Üks võimalus ongi vaadata NFC Forum Tage, kui väikseid kontaktivabasid mälukaarte. Millega andme vahetus toimub NDEF (NFC Data Exchange Format) kirjetena. NFC Forum on määratlenud viis erinevat Tagi tüüpi (Type1-5).

Sagedusel 13,56 MHz lainepikkus on u 22m.

NFC lainepikkus

Vastavad täielikult NFC Forum Type 2 Tag ja ISO/IEC14443 Type A standardile. Märgiseid saab kuni 100 000 korda ülekirjutada ja lubatakse, et andmed säilivad vähemal 10 aastat.

Andmeedastus kiirus 106 kbit/s.

Igal märgisel on oma unikaalne 7-baidine ID kood.

On erineva mälu suurusega:

NimiVaba kasutatav mälu
NTAG 213144 baiti
NTAG 215504 baiti
NTAG 216888 baiti
NFC NTAG 213

Elecrow ESP32 touch display and Ubuntu

I recently got this small touch display 480×320 with a built-in ESP32-S3 module from Elecrow. I had problems programming it and it turned out that Ubuntu 22.04 does not have a CH340 driver so we have to install it manually. Steps to do this:

1 . Uninstall brltty (Unless you have vision problems and you actually need this).

sudo apt remove brltty

2. Download this GitHub repository: github.com/juliagoda/CH341SER

git clone -b ubuntu https://github.com/juliagoda/CH341SER.git

3. Unzip and go inside, open the terminal and run: make

make

4. Load module

sudo make load

5. Add permissions

sudo usermod -aG dialout $username
sudo chmod a+rw /dev/ttyUSB0

6. Verify

ls -la /dev/ttyUSB0

7. If you Upload, hold down the Boot button (behind the screen). And press the Reset button once.

Links: