From my reading and experimentation I have found that Android devices use some method to prevent duplicate reading of a tag (as discussed here). This is great for power cons
Superb answer from Michael. But I'm seeing a problem. When the microcontroller on the tag performs an i2c read of the non-volatile memory in the NFC device, it would seem that it risks interfering with the "pinging" that is being done by the phone.
I'm using a Motorola G6 Play phone with something very similar to the M24LR-DISCOVERY tag which has a M24LR04E-R. [I have reproduced the results for the ST25DV.] The tag is powered from a bench supply NOT from energy harvesting for this experiment.
When the tag is in the field of the phone, I can see activity in logcat of the Android debugger every 130ms or so.
2020-10-13 19:38:50.555 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(793)] nfaConnectionCallback: Connection Event = 15
2020-10-13 19:38:50.555 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(1389)] nfaConnectionCallback: NFA_PRESENCE_CHECK_EVT
2020-10-13 19:38:50.680 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1953)] nativeNfcTag_doPresenceCheck
2020-10-13 19:38:50.680 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1997)] nativeNfcTag_doPresenceCheck: handle=0
2020-10-13 19:38:50.694 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(793)] nfaConnectionCallback: Connection Event = 15
2020-10-13 19:38:50.694 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(1389)] nfaConnectionCallback: NFA_PRESENCE_CHECK_EVT
2020-10-13 19:38:50.820 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1953)] nativeNfcTag_doPresenceCheck
2020-10-13 19:38:50.820 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1997)] nativeNfcTag_doPresenceCheck: handle=0
This appears to be Android checking for the presence of the tag. During this time I see the RF_BUSY output of the M24LR go low for about 15ms every 130ms or so. I associate this with the Android activity above.
If the microcontroller then does a block read over i2c of the M24LR memory, then shortly afterwards the phone plays a notification tone. What has happened is that the phone has lost connection with the tag and reconnected. The logcat output for this time shows this happening without warning.
2020-10-13 19:38:51.335 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(793)] nfaConnectionCallback: Connection Event = 15
2020-10-13 19:38:51.335 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(1389)] nfaConnectionCallback: NFA_PRESENCE_CHECK_EVT
2020-10-13 19:38:51.335 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(2173)] nativeNfcTag_doPresenceCheck: tag absent
2020-10-13 19:38:51.335 4209-28960/? D/NativeNfcTag: Tag lost, restarting polling loop
2020-10-13 19:38:51.335 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1392)] nativeNfcTag_doDisconnect: enter
2020-10-13 19:38:51.335 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1414)] nativeNfcTag_doDisconnect: exit
2020-10-13 19:38:51.336 4209-28960/? D/NfcService: Discovery configuration equal, not updating.
2020-10-13 19:38:51.336 4209-28960/? D/NativeNfcTag: Stopping background presence check
2020-10-13 19:38:51.344 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(793)] nfaConnectionCallback: Connection Event = 6
2020-10-13 19:38:51.344 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(1121)] nfaConnectionCallback: NFA_DEACTIVATED_EVT: Type=0, gIsTagDeactivating=0
2020-10-13 19:38:51.344 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(5280)] notifyPollingEventwhileNfcOff: sDiscCmdwhleNfcOff=0
2020-10-13 19:38:51.344 4209-4411/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(921)] getReconnectState = 0x0
2020-10-13 19:38:51.345 4209-4411/? I/libnfc_nci: [INFO:NfcTag.cpp(189)] NfcTag::setDeactivationState: state=0
2020-10-13 19:38:51.345 4209-4411/? I/libnfc_nci: [INFO:NfcTag.cpp(1358)] NfcTag::resetTechnologies
2020-10-13 19:38:51.345 4209-4411/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(263)] nativeNfcTag_abortWaits
The disconnect connect obviously plays havoc with any app running on the phone that is trying to exchange information with the tag.
I tried using the BUSY signal to prevent the microcontroller on the tag starting any i2c read operations when the RF access was in progress but the problem still occurs. I'm guessing that the problem is due to an RF ping happening when a memory access is in progress but I'm only guessing.
It seems that the chances of a disconnect increase with the number of bytes read (supporting the idea of a "clash".) Single byte reads can often get away without causing a disconnect.
Can this really be the correct behaviour? Is there nothing that can be done to prevent this? How would the OP (or myself) use these devices to implement a system whereby a microcontroller on the tag could read/write the memory of the NFC device to exchange information with an app running on the phone? As I said, I have observed this with both M24LR and ST25DV.
[Apologies if this is more of a question than an answer, but I wanted to shed some more light on the subject.]
What you state in your question is simply not true for Android NFC devices. Once a tag has been detected (= valid tag that responsed to all mandatory commands and could potentially be dispatched to an app), the NFC reader will continuously power the tag (HF carrier is kept on) and exchange some commands with it. The commands that are exchanged during that keep-alive phase ("presence check") depend on the tag type, the Android version and the Android NFC stack implementation. This is typically either
that allows the NFC stack to find out if the tag is still responsive. Only if the presence check fails, Android will switch off the HF carrier of the NFC reader and will re-start with either a full polling sequence (testing for all kinds of supported tag technologies) or with a sensing phase (short HF carrier pulses to detect detuning that indicates the potential presence of a tag).
Thus, if your tag behaves properly and your users manage to keep a tag attached to the Android device for a longer period of time, there is nothing that would prevent you from reading new data from the same tag (while continuously attached) multiple times. You just need to make sure that you keep the tag handle (Tag
object or even a specific tag technology object instantiated from that tag handle) for as long as you want to access the tag and the tag reading activity of your app needs to stay continuously in the foreground.
You could, for instance, do something like this to read a continuously updated NDEF message from a tag (note that you might better want to use an AsyncTask
(or similar) instead of simply spawning that thread AND you might want to implement some mechanism to interrupt the thread):
new Thread(new Runnable() {
public void run() {
Ndef ndef = Ndef.get(tag);
try {
while (true) {
try {
Thread.sleep(30000);
ndef.connect();
NdefMessage msg = ndef.getNdefMessage();
// TODO: do something
} catch (IOException e) {
// if the tag is gone we might want to end the thread:
break;
} finally {
try {
ndef.close();
} catch (Exception e) {}
}
}
} catch (InterruptedException e) {
}
}
}).start();