Enter Your Project for a chance to win a Spectrum Analyzer for the Most Innovative RF Project! | Project14 Home | |
Monthly Themes | ||
Monthly Theme Poll |
Following on my last post about a surprise care package from element14, it didn't come with no strings attached. In fact, it came with this message penned by an anonymous tariq.ahmad (I think) which says:
I've not entered any of the monthly challenges in the past, but seeing as I have a package with an invitation, I thought I might as well give it a crack. After all, I am a licensed radio amateur (VK2FGYL) with an interest in many things including radio and I had a long-brewing idea that I had wanted to complete but never found the impetus to actually get started. It comes at a good time, as this time, the Project14 RF competition overlaps with Makevember which encourages people to get "making"! Even though there is a long time to the deadline, I decided to get something in as quickly as I can because things can change at an instant - I'm also handling a RoadTest concurrently.
A Little Bit about NFC
NFC is short for Near Field Communication, a technology used for "contactless" communication between readers and smart cards/tags. You might encounter this every-day in the form of contactless payments on your phone or credit/debit card, certain sorts of access control cards and transportation cards, and NDEF advertising tags which can be scanned to open up a URL/store contact details/etc. These devices are similar to, but not identical to RFID, as they are intended for short-range usage only and can feature more than just identification. Smart cards frequently feature memory, cryptographic processing units and microcontrollers. This has always been an interesting technology for me - as it seemed rather magical compared to the barbaric ways of the old magnetic stripe.
At the moment, it seems that most of the NFC technologies are either ISO-standard compatible or pre-standard Sony Felica systems. A commonality to all of these systems is the use of 13.56MHz as the carrier frequency emitted by the reader which serves to both power the card and provide a frequency reference for subcarrier modulation or load/backscatter modulation to send data back and forth from the card. Owing to the power demands of the smart cards (which are at most, modest), NFC readers typically put out a fairly decent field strength into a loop antenna. A good antenna is fairly difficult to design for this application, as it can also depend on the tags/cards you use with the system - ultimately, the aim is to maximise inductive coupling (rather than radiation) through magnetic fields and avoid transmitting harmonics (i.e. filter out-of-band emissions).
As the technology has become relatively common, it has seen integration into mobile phones and smart watches for payment purposes amongst other uses. The power consumption of NFC can be kept fairly low - this is done by pulsing the field on-and-off periodically to sense whether a card or device is present and only keeping the field on when active communication is happening. There is also a mode for peer-to-peer usage, as a new usage scenario is the presence of powered devices on both ends which can take turns generating the field for communication rather than relying on the reader alone.
This got me thinking - 13.56MHz is within the "license-free" ISM band and is an HF frequency close in wavelength to the 20m band (14MHz) which is known to propagate well during the daytime. I wondered if NFC signals would propagate any significant distance from a reader - after all, it is called near field communication, so the expectation is that the signal wouldn't propagate very far. Indeed, this may be true of the backscatter modulation signal from a card - but what about the reader's carrier wave? What if we used it to encode some data?
What is QRSS?
QRSS is radio shorthand for send really slowly. This mode basically entails using CW (or later, using FSK, DFCW or more exotic modes) at a very slow rate to reduce the signal bandwidth and increase signal to noise ratio (assuming a receiver bandwidth matching the transmitter closely). This necessarily results in a trade-off - slower send rates allow lower-power operation but optimally require highly-frequency stable transmitters. Transmission distances of over 1000 miles per watt have been achieved and verified, with a small community of monitors around the world plotting spectrum on QRSS grabbers to assess propagation characteristics over time. The patterns the signals make are fascinating - but so are many of the signal's excellent GPS-stabilised frequency stability.
This has been something I've wanted to try, but as my foundation callsign license doesn't permit homebrew and has limitations on the use of certain bands, I would have to upgrade my license if I were to do it in the amateur bands. But if I perhaps give it a try by abusing an NFC transmitter - I'd be legal as it'd be in ISM band and I might still gain some advantage from the HF frequency propagation. Just a thought ...
Getting it Together
About six years ago, I had already purchased everything necessary to make a proof of concept trial of the idea - but I never had the impetus to try making it happen until now.
The parts used included:
- Raspberry Pi Model A - this is the bare-bones original model A with just one USB port and no network connectivity. Feel free to substitute a modern Raspberry Pi - it should work just fine.
- Wi-Pi Adapter - as the Model A has no connectivity, I used the Wi-Pi to add Wi-Fi connectivity to the unit.
- Sandisk 4GB MicroSD card with adapter - another small "scrap" card I had lying about - any card bigger than 4GB would do just fine.
- NXP NFC-EXPLORE add-on board - this provides the PN512 NFC radio interface with onboard 4-turn printed trace antenna and forms the transmitter.
- USB 5V/2A power supply and USB A to micro-B cable - to power the Raspberry Pi.
- Icom IC-R20 Communications Receiver - for handheld monitoring of the signal while moving about.
- Degen DE1103 - tabletop portable shortwave receiver with SSB, as a secondary monitoring station.
- Winradio WR-G31DDC SDR - to monitor the signal locally on the computer while comparing it with signals from other KiwiSDRs on the web.
In order to get this set-up, I followed the following procedures:
- Imaged the card with the latest version of Raspbian Buster Lite from the Raspberry Pi Foundation's website.
- Enabled SSH and configured Wi-Fi in a headless mode by adding 'ssh' and 'wpa_supplicant.conf' files to the BOOT partition.
- Logged into the unit via SSH and changed the password using passwd.
- Configured the hostname, regional locale, time-zone, memory split, overclocking and SPI interface using sudo raspi-config.
- Updated the installation to the latest packages using sudo apt-get update, sudo apt-get upgrade, and sudo apt-get dist-upgrade.
- Cleaned any excess cached files from the unit by running sudo apt-get clean to reclaim the space.
- Downloaded the necessary EXPLORE-NFC files by signing up to NXP and downloading them from this page. Surprisingly, after all these years, it still seems supported.
- Installed the NFC Reader Library first by issuing sudo apt-get install build-essential cmake python3-dev python2.7-dev and then sudo dpkg -i NFC-Reader-Library-4.010-2.deb.
- Installed the remaining examples by using sudo dpkg -i libneardal0_0.14.3-1_armhf.deb neard-explorenfc_1.2-1_armhf.deb,
- Installed pip for Python by using sudo apt-get install python-pip python3-pip.
- Installed nxppy by using sudo pip install nxppy and sudo pip3 install nxppy.
This left me with an environment where I could begin developing for the EXPLORE-NFC board and test its functionality. The demonstration programs worked right out of the box - so I went directly to writing a program instead.
Ideally, I would have worked with the SPI interface and talked to the PN512 chip directly, but it is a rather complex device. As Python is convenient, I opted to use nxppy, but it seems that it abstracts a number of key hardware features away from the user. Referencing the PN512's datasheet, it did not seem straightforward to enable or disable the field directly, as it seemed to be a "smarter" IC that tried to handle some of the work within itself. As a result, I was left to do some kludging about when I realised that any card operation done will turn on the field and leave it on indefinitely. However, turning the field off was not as obvious - there is no direct "close", "end" function and closing the program doesn't shut the field down either. Without this capability - I would be stuck. It was by chance that I found that initialising a new Mifare constructor would cause the field to be turned off - hence I used this as the method of shutting the field off even though it was "slow".
This was not a sure fire win either, as running a program for a while, constantly re-opening the device, led to issues with pthread and a mutex lock being incorrectly accessed, crashing the program. Unfortunately, I don't have a solution for this directly - but for relatively short messages (which is what you might want to use it for anyway), it worked just fine. Instead, I would re-invoke the program from the shell in case it crashes, causing a "partial" message to be sent.
The code developed (rather quickly) and looks as follows (with some sections borrowed from GeeksforGeeks):
import nxppy import time MORSE_CODE_DICT = { 'A':'.-', 'B':'-...', 'C':'-.-.', 'D':'-..', 'E':'.', 'F':'..-.', 'G':'--.', 'H':'....', 'I':'..', 'J':'.---', 'K':'-.-', 'L':'.-..', 'M':'--', 'N':'-.', 'O':'---', 'P':'.--.', 'Q':'--.-', 'R':'.-.', 'S':'...', 'T':'-', 'U':'..-', 'V':'...-', 'W':'.--', 'X':'-..-', 'Y':'-.--', 'Z':'--..', '1':'.----', '2':'..---', '3':'...--', '4':'....-', '5':'.....', '6':'-....', '7':'--...', '8':'---..', '9':'----.', '0':'-----', ',':'--..--', '.':'.-.-.-', '?':'..--..', '/':'-..-.', '-':'-....-', '(':'-.--.', ')':'-.--.-'} def radio_tx (on) : mifare=nxppy.Mifare() if (on) : try: mifare.select() except nxppy.SelectError: pass def send_msg (message,timebase) : for letter in message: if letter == ' ' : time.sleep(timebase*3) elif letter == '.' : radio_tx(1) time.sleep(timebase) radio_tx(0) time.sleep(timebase) elif letter == '-' : radio_tx(1) time.sleep(timebase*3) radio_tx(0) time.sleep(timebase) time.sleep(timebase*3) def morse(message): morse = '' for letter in message: if letter != ' ': morse += MORSE_CODE_DICT[letter] + ' ' else: morse += ' ' return morse message="URCALL" timebase = 30 encoded = morse(message) send_msg(encoded,timebase)
Aiming Far ... and Falling Short
Having now written the code, I decided I would try changing the timebase for various demonstration purposes. QRSS typically gets the furthest using long "dot" times, but this necessarily slows the data transmission rate to a crawl. At 90s per dot, my callsign takes about three hours to transmit. But before we can run, we must walk, so some local testing is necessary.
The first step was to see whether the signal was visible at all. Turning on my Winradio Excalibur WR-G31DDC, I was greeted with the signal from the NFC reader at 13560.628kHz. Considering that my WR-G31DDC has been calibrated to <1ppm compared to time reference stations WWV/WWVH, I'd have confidence that we know the frequency to within about 20Hz.
Changing the message to my callsign followed by element14, it was possible to get this plot of the output using Spectrum Lab examining the audio output from the SDR in fixed gain mode via a Virtual Audio Cable. At a dot rate of 0.5s/dot, it was possible to get a decent morse code representation, although the timing wasn't quite perfect due to delays within the Raspberry Pi. Given this was not its intended use, I am inclined to forgive these timing transgressions. The signal also seemed to have some harmonics and a rather rough note - this is not unexpected, as it was not a transmitter designed to have the best output purity.
I changed to a slower 3s/dot rate for a better signal, this time using a software called Argo which is a much simpler software with QRSS settings pre-configured. At the slower rate, timing variations were much less compared to the dot length, to the point of not being noticeable. I decided this would be a good time to see if my signal would propagate - as QRSS seems to show signals travelling over 1000 miles per watt, so with about 0.1W at a guess, I should be able to get about 160km assuming the best.
I opted for the longest 90s/dot rate to maximise my chances of travelling far. I selected Mediaexplorer's KiwiSDR in Freemans Reach, just 20km from my house, with my NFC EXPLORE card pointed towards the receiver at the highest point in the house. I configured the KiwiSDR receiver to play through the virtual audio cable into Spectrum Lab, but also configured my local Winradio SDR to output a band-limited signal, shifted downward in frequency, so I can see my own transmission and try to correlate it to what was being received from the remote receivers via the internet. It was only through this exercise that I could see the frequency instability of the NFC radio which was not ideal, but also the fact there is competing interference from other NFC devices which seems to come and go. Unfortunately, in the band where I expected to see something, I saw nothing. I suspected that the first receiver I chose may have had a higher noise floor, so I chose Tecsun Radios Australia's KiwiSDR which was further away - but even there I had no luck.
I monitored for a while longer without the local receiver - while there were the occasional traces of noise, nothing "beacon-like" appeared. Signals did not fade-in or fade-out as I had hoped - maybe propagation wasn't favouring me. But I decided that perhaps I was too ambitious from the outset and needed to scale back my expectations slightly.
Going back to a relatively quick 0.5s/dot rate which I could tolerate listening to, I walked around the neighbourhood with my communications receiver and a whip antenna about 60cm tall. In all, I could only hear my signal from a distance of about 70m away - further than that, it seemed to disappear into the noise, but a slower dot rate and FFT display could probably bring it back out. More than that, competing sources of interference made themselves audible, although due to their frequency offsets, it was possible to distinguish my transmission from theirs. In all, I concluded that it was likely that the antenna itself was not designed to be a good radiator - instead, it was designed to inductively couple with smart cards and tags, hence a modified antenna would be necessary if the range is to be extended significantly. However, from this walk test, the fact I even reached 70m was an achievement in my eyes - audio attached to this post at the end, recorded from the IC-R20 using its internal IC Recorder.
Video
As required for the Project14 submission - here's my video of my solution:
Conclusion
NFC is normally thought of as a close-range protocol and yet the carrier field emitted by a reader can actually travel quite far. The field itself can be modulated by the software running on a smartphone, or in this case, through direct commands sent from the Raspberry Pi to the PN512 NFC controller. As a result, it is possible to run the NFC radio as an on-off keying radio, generating an interrupted carrier wave which travels quite a distance (70m audible on a whip antenna, potentially further with better encoding techniques). This would be a slow means of data exfiltration, but could be rather difficult for a user to notice as it wouldn't jam any other readers or cause much inconvenience except when actually actively using the NFC. This means of data exfiltration is perhaps not a preferred one, but could be quite effective in the right circumstances.
As other NFC readers may interfere with the transmission, slower and longer transmission modes (e.g. QRSS or chip-based modes) can be used to try and bring the signal out of the noise and filter out adjacent-frequency interferers, however the fixed frequency and limited stability oscillator is not ideal for this purpose. The antenna of most devices are optimised for inductive coupling through magnetic field and also does not do a great job of radiating the signal across longer distances without modifying the device - in which case, matching of the antenna and filtering components becomes necessary to avoid spurious outputs.
Of course, there's no cause for alarm just yet - but I just find it nifty that I could abuse the NFC radio to form a QRSS-style morse code beacon that could be received over four houses away without modifying the hardware at all. Perhaps I could abuse the Raspberry Pi's GPIO pin using something like rpitx, but the big issue would be building an appropriate filter that keeps out-of-band emissions at bay. I don't want to be polluting the airwaves indiscriminately, especially when I'm sending out my callsign!
Top Comments