├── .DS_Store
├── README.md
├── arduino
├── .DS_Store
└── NFCSense4P_ArduinoUno_RC522_v1
│ ├── NFCSense4P_ArduinoUno_RC522_v1.ino
│ ├── RFID.cpp
│ └── RFID.h
├── docs
└── NFCSenseCheatSheet_v1.png
├── download
├── .DS_Store
└── OpenNFCSense4P-2.zip
├── examples
├── .DS_Store
├── episode1
│ ├── .DS_Store
│ ├── e1_SingleTagEFan
│ │ ├── .DS_Store
│ │ ├── data
│ │ │ └── tagProfile.csv
│ │ └── e1_SingleTagEFan.pde
│ ├── e1_SingleTagRoulette
│ │ ├── .DS_Store
│ │ ├── data
│ │ │ └── tagProfile.csv
│ │ └── e1_SingleTagRoulette.pde
│ └── e1_SingleTagWheel
│ │ ├── .DS_Store
│ │ ├── data
│ │ └── tagProfile.csv
│ │ └── e1_SingleTagWheel.pde
└── episode2
│ ├── .DS_Store
│ ├── e1_SingleTagAlpha
│ ├── .DS_Store
│ ├── data
│ │ └── tagProfile.csv
│ └── e1_SingleTagAlpha.pde
│ ├── e1_SingleTagLoops
│ ├── .DS_Store
│ ├── data
│ │ ├── apple.png
│ │ ├── banana.png
│ │ ├── carrot.png
│ │ └── tagProfile.csv
│ └── e1_SingleTagLoops.pde
│ ├── e1_SingleTagNumSym
│ ├── .DS_Store
│ ├── data
│ │ ├── apple.png
│ │ ├── banana.png
│ │ ├── carrot.png
│ │ └── tagProfile.csv
│ └── e1_SingleTagNumSym.pde
│ ├── e1_SingleTagNums
│ ├── .DS_Store
│ ├── data
│ │ └── tagProfile.csv
│ └── e1_SingleTagNums.pde
│ └── e1_SingleTagSelfDefined
│ ├── .DS_Store
│ ├── data
│ ├── .DS_Store
│ ├── apple.png
│ ├── banana.png
│ ├── carrot.png
│ └── tagProfile.csv
│ └── e1_SingleTagSelfDefined.pde
├── figures
├── hardware.png
└── playlist.png
└── src
├── .DS_Store
└── OpenNFCSense4P
├── NFCBit.java
└── OpenNFCSense4P.java
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/.DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenNFCSense API
2 | Open-source API of NFCSense for the Processing programming environment (http://processing.org/). Please refer to the following workflow to start experiencing the NFCSense!
3 |
4 | by [Dr. Rong-Hao Liang](https://ronghaoliang.page) (Last update: May 26, 2021)
5 |
6 | _Now it's **V2: Basic Tutorial and Examples** are available!_
7 |
8 | [](docs/NFCSenseCheatSheet_v1.png)
9 |
10 | ## NFCSense Project website:
11 | - [https://ronghaoliang.page/NFCSense/](https://ronghaoliang.page/NFCSense/)
12 |
13 | ### Check the Open Access Paper at ACM Digital Library:
14 | - [HTML](https://dl.acm.org/doi/fullHtml/10.1145/3411764.3445214)
15 | - [PDF](https://dl.acm.org/doi/pdf/10.1145/3411764.3445214)
16 |
17 | ## NFCSense Video Tutorials
18 | [](https://youtube.com/playlist?list=PLSgbdfV4TB2f16s4GMy_-1ZMu_zGP9QIH)
19 | - [Episode 2: Making Educational Toys with Lego Bricks](https://youtu.be/lkaZDMGdLuQ)
20 | - [Episode 1: Making Toys with Things That Rotate](https://youtu.be/jzElM6CWH4s)
21 | - [Episode 0: Setting Up the OpenNFCSense API](https://youtu.be/Gal2keOJShM)
22 | ### All the examples shown in the videos are in the /examples folder
23 |
24 | ## Prerequisite (for V2)
25 | - 1x Arduino Uno board
26 | - 1x RC522 NFC reader
27 | - A few NFC tags (e.g., Mifare 1k, NTAG213, NTAG215)
28 | - A computer installed Processing and Arduino IDEs
29 |
30 | ## Download (/download)
31 | The OpenNFCSense API V2 of the Processing Library (OpenNFCSense4P-2.zip) in zip format.
32 |
33 | ### Install the processing library - OpenNFCSense API
34 | - Video: [Episode 0: Setting Up the OpenNFCSense API](https://youtu.be/Gal2keOJShM)
35 | - Unzip and put the extracted OpenNFCSense folder into the libraries folder of your Processing sketches. Reference and examples are included in the OpenNFCSense folder. Then, Restart your Processing software. New examples can be found in the processing library.
36 |
37 | ## Preparation: Upload the Arduino code (/arduino) and Connect the Reader
38 | - Video: [Episode 0: Setting Up the OpenNFCSense API](https://youtu.be/Gal2keOJShM)
39 | - Upload the arduino code to your Arduino board first! This software works with a microcontroller connected to an RC522 NFC/RFID Reader and run the Arduino code: NFCSense4P_ArduinoUno_RC522_v1.ino.
40 | - Connect the RC522 NFC reader to the Arduino board as follows (via the Arduino's SPI)
41 | 
42 |
43 | ## Use the OpenNFCSense API by Examples
44 | ### e1_SingleTagRotation
45 | - Video: [Episode 1: Making Toys with Things That Rotate](https://youtu.be/jzElM6CWH4s)
46 | - Video: [Episode 2: Making Educational Toys with Lego Bricks](https://youtu.be/lkaZDMGdLuQ)
47 | - Open the example e1_SingleTagRotation.pde
48 | - Attach an NFC tag to anything that spins, such as a fidget spinner.
49 | - Run the processing sketch, scan the tag, and keep the tag's 4-byte Universal ID (UID0,UID1,UID2,UID3) shown in the console. Close the processing sketch.
50 | - Open the data/tagProfile.csv in the examples' folder, replace the UID of "Black spinner" with yours, save the CSV file.
51 | - Run the processing sketch again, spin the your spinner, and then you will see the object info and the rotation frequecy shown on the screen as "Recent tag: [Label] is spinning at ? Hz".
52 | - In the data/tagProfile.csv, You may replace the "Black spinner" label to any name (avoid using comma). You can make another row with the same format to be able to recognize multiple spinners!
53 |
54 | ### e2_SingleTagSwinging
55 | - Open the example e2_SingleTagSwinging.pde
56 | - Attach an NFC tag to anything that swings, such as a finger.
57 | - Run the processing sketch, scan the tag, and keep the tag's 4-byte Universal ID (UID0,UID1,UID2,UID3) shown in the console. Close the processing sketch.
58 | - Open the data/tagProfile.csv in the examples' folder, replace the UID of "Swing" with yours, save the CSV file.
59 | - Run the processing sketch again, spin the your spinner, and then you will see the object info and the rotation frequecy shown on the screen as "Recent tag: [Label] is swining at ? Hz".
60 | - In the data/tagProfile.csv, You may replace the "Swing" label to any name (avoid using comma). You can make another row with the same format to be able to recognize swinging objects!
61 |
62 | ### e3_TagSequence
63 | - Open the example e3_TagSequence.pde
64 | - Attach an NFC tag to the bottom of any objects, such as a duplo block that has a letter printed on its surface. Maintain z=8-25mm (for Mifare 1k or NTAG 213/215 tags) distance between the tag and the reader with an optional linear track for reliable tracking.
65 | - Run the processing sketch, scan the tag, and keep the tag's 4-byte Universal ID (UID0,UID1,UID2,UID3) shown in the console. Then, close the processing sketch.
66 | - Open the data/tagProfile.csv in the examples' folder, replace the UID with yours, save the CSV file.
67 | - Run the processing sketch again, scan your object, and then you will see object shown in list of a recent tag.
68 | - In the data/tagProfile.csv, You may replace the "A" label to any name (avoid using comma). Likewise, you add the 2nd, 3rd, and more object's UIDs and label to the CSV profile. Save the profile and run the processing sketch again, and your reader should be able to read all of them.
69 | - The list of "recent tag" will be cleared up when the reader does not read a new tag for 1000 ms (1 s) by default. You may change it to 2 seconds by setting up a parameter to the constructor as `nfcs = new OpenNFCSense4P(this, "demo.csv", 300, 300, 2000)` to set the TTL timer2 to 2000.
70 |
71 | ### e4_CompoundRotation
72 | - Open the example e4_TagSequence.pde
73 | - Attach __3__ NFC tags to anything that spins, such as a fidget spinner. Don't let the tags overlap.
74 | - Run the processing sketch, scan one of the tag, and keep the first tag's 4-byte Universal ID (UID0,UID1,UID2,UID3) shown in the console. Then, rotate the object counterclockwisely and get the second tag's 4-byte UID. Then rotate the object counterclockwisely and get the third tag's 4-byte UID. close the processing sketch.
75 | - Open the data/tagProfile.csv in the examples' folder, replace the UID of the three "white spinner" tags with yours. The first tag goes first, and then the second and the third. Save the CSV file after it's done.
76 | - Run the processing sketch again, spin the object, and then you will see the object's info, the rotation direction and frequecy shown on the screen as "Recent tag: [Label] is spinning \n (counter)clockwise at ? Hz". In recent tags you also see the sequence of the tag presence.
77 | - In the data/tagProfile.csv, You may replace the "White spinner" label to any name (avoid using comma). Likewise, you add more object's UIDs and label to the CSV profile. Save the profile and run the processing sketch again, and your reader should be able to read all of them.
78 |
79 | ### e5_CompoundLinear
80 | - Open the example e5_CompoundLinear.pde
81 | - Attach __2__ NFC tags to anything that moves linearly, such as a trolley. Don't let the tags overlap. Maintain z=8-25mm (for Mifare 1k or NTAG 213/215 tags) distance between the tag and the reader with a linear track for reliable tracking.
82 | - Run the processing sketch, scan one of the tag, and keep the first tag's 4-byte Universal ID (UID0,UID1,UID2,UID3) shown in the console. Then, scan the second tag and get its 4-byte UID. Close the processing sketch.
83 | - Open the data/tagProfile.csv in the examples' folder, replace the UID of the two "trolley" tags with yours. The first tag goes first, and then the second. Replace the number 34.0 of the both tag with the actual distance between the center of the two tags (e.g., set 38.0 when the distance is 38mm). Save the CSV file after it's done.
84 | - Run the processing sketch again, move the object linearly, and then you will see the object's info, the movement direction and speed shown on the screen as "Recent tag: [Label] is moving \n forward/backward at ? km/h". In recent tags you also see the sequence of the tag presence.
85 | - In the data/tagProfile.csv, You may replace the "Trollety" label to any name (avoid using comma). Likewise, you add more object's UIDs and label to the CSV profile. Save the profile and run the processing sketch again, and your reader should be able to read all of them.
86 |
87 | ### e6_SingleTagHovering
88 | - Open the example e6_SingleTagHovering.pde
89 | - Attach __1__ NFC tags to the top of anything that moves linearly, such as a boat. Maintain z = 7-25 mm (for Mifare 1k or NTAG 213/215 tags) distance between the tag and the reader with a linear track for reliable tracking.
90 | - Run the processing sketch, scan the tag, and keep the tag's 4-byte Universal ID (UID0,UID1,UID2,UID3) shown in the console. Close the processing sketch.
91 | - Open the data/tagProfile.csv in the examples' folder, replace the UID of the "boat" tags with yours. Save the CSV file after it's done.
92 | - Run the processing sketch again, move the object linearly, and then you will see the object's info, the movement direction and speed shown on the screen as "Recent tag: [Label] is sliding at ? km/h". **Note: This speed is not correct yet.** We measure the tag activation path length using a ruler. By checking the moving bar on the screen, we can get the reader of the path activation length as X mm.
93 | - In the data/tagProfile.csv, replace the L1 from 43.0 to the X that you measured (e.g., 39.0 when X = 39mm). You may replace the "Boat" label to any name (avoid using comma). Save the profile and run the processing sketch again, and **your reader will be able to read the correct speed** of the tag movement.
94 | - Likewise, you can add more object's UIDs, label, and L1 to the CSV profile.
95 |
96 | ### e7_SingleTagSlidingHovering
97 | - Open the example e7_SingleTagSlidingHovering.pde
98 | - Attach __1__ NFC tags to the bottom of anything that moves linearly, such as a figurine. Maintain less than 6mm distance (for Mifare 1k or NTAG 213/215 tags) between the tag and the reader with a linear track.
99 | - Run the processing sketch, scan the tag, and keep the tag's 4-byte Universal ID (UID0,UID1,UID2,UID3) shown in the console. Close the processing sketch.
100 | - Open the data/tagProfile.csv in the examples' folder, replace the UID of the "figurine" tags with yours. Save the CSV file after it's done.
101 | - Run the processing sketch again, move the object linearly, and then you will see the object's info, the movement direction and speed shown on the screen as "Recent tag: [Label] is sliding at ? km/h". **Note: This speed is not correct yet.** We need to measure the tag activation path lengths with a ruler.
102 | - Two tag activation path lengths have to be measured: 1) L1 for Sliding, and 2) L2 for Hovering. For L1 (sliding), since there will be 3 segments of activation that are observable, check the longest one on the screen so that you can get the L1 = X mm. For L2 (hovering), put a spacer below the tag to make the z>6mm. There will be only one segment of activation that is observable so that you can get L2 = Y mm.
103 | - In the data/tagProfile.csv, replace the L1 from 39.0 to the X that you measured and the L2 from 43.0 to the Y that you measured. You may replace the "Figurine" label to any name (avoid using comma). Save the profile and run the processing sketch again, and **your reader will be able to read the correct speed** of the tag movement in the both modes. The hovering speed can be less accurate if the object is above z=25mm.
104 | - Likewise, you can add more object's UIDs, label, L1 and L2 to the CSV profile.
105 |
106 | ### e8_SingleTiltedTagSliding
107 | - Open the example e8_SingleTiltedTagSliding.pde
108 | - Attach __1__ tilted (between 60-75 degree) NFC tags to the bottom of anything that moves linearly, such as a car. Maintain less than 22mm distance (for Mifare 1k or NTAG 213/215 tags) between the tag's center and the reader with a linear track.
109 | - Run the processing sketch, scan the tag, and keep the tag's 4-byte Universal ID (UID0,UID1,UID2,UID3) shown in the console. Close the processing sketch.
110 | - Open the data/tagProfile.csv in the examples' folder, replace the UID of the "Car" tags with yours. Save the CSV file after it's done.
111 | - Run the processing sketch again, move the object linearly, and then you will see the object's info, the movement direction and speed shown on the screen as "Recent tag: [Label] is sliding forward/backward at ? km/h". **Note: This speed is not correct yet.** We need to measure the tag activation path lengths with a ruler.
112 | - Since there will be 2 segments of activation that are observable, check the longest one on the screen so that you can get the L1 = X mm.
113 | - In the data/tagProfile.csv, replace the L1 from 31.0 to the X that you measured. You may replace the "Car" label to any name (avoid using comma). Save the profile and run the processing sketch again, and **your reader will be able to read the correct speed** of the tag movement in both directions.
114 | - Likewise, you can add more object's UIDs, label, L1 to the CSV profile.
115 |
116 | ### e9_Demo
117 | - Open the example e9_Demo.pde
118 | - Copy the lines that you just created from the tagProfile.csv files in the previous examples to the demo.csv.
119 | - Run the processing sketch, then every object's movement mode and it's correct speed can be detected.
120 |
121 | ### e0_App_Boilerplate
122 | - Open the example e0_App_Boilerplate.pde
123 | - Copy the lines that you just created from the tagProfile.csv or demo.csv files in the previous examples to the demo.csv.
124 | - Now you can use this processing sketch as a boilerplate to create your own applications.
125 |
126 | ## Cheatsheet (/docs)
127 | The 1-page Summary of how the proposed algorithm works.
128 |
129 | ### Documentation
130 | The full documentation will be available soon!
131 |
132 | ## Source (/src)
133 | The source code of the OpenNFCSense library (**GNU GPLv3 copyleft license**)
134 |
135 | ## Cite this Work:
136 |
137 | If you use this library, please cite the original NFCSense paper as following
138 |
139 | - ACM format:
140 | ```
141 | Rong-Hao Liang and Zengrong Guo. 2021. NFCSense: Data-Defined Rich-ID Motion Sensing for Fluent Tangible Interaction Using a Commodity NFC Reader. In Proceedings of the 2021 CHI Conference on Human Factors in Computing Systems (CHI '21). Association for Computing Machinery, New York, NY, USA, Article 505, 1–14. DOI:https://doi.org/10.1145/3411764.3445214
142 | ```
143 | - bibtex format:
144 | ```
145 | @inproceedings{10.1145/3411764.3445214,
146 | author = {Liang, Rong-Hao and Guo, Zengrong},
147 | title = {NFCSense: Data-Defined Rich-ID Motion Sensing for Fluent Tangible Interaction Using a Commodity NFC Reader},
148 | year = {2021},
149 | isbn = {9781450380966},
150 | publisher = {Association for Computing Machinery},
151 | address = {New York, NY, USA},
152 | url = {https://doi.org/10.1145/3411764.3445214},
153 | doi = {10.1145/3411764.3445214},
154 | abstract = { This paper presents NFCSense, a data-defined rich-ID motion sensing technique for fluent tangible interaction design by using commodity near-field communication (NFC) tags and a single NFC tag reader. An NFC reader can reliably recognize the presence of an NFC tag at a high read rate (∼ 300 reads/s) with low latency, but such high-speed reading has rarely been exploited because the reader may not effectively resolve collisions of multiple tags. Therefore, its human–computer interface applications have been typically limited to a discrete, hands-on interaction style using one tag at a time. In this work, we realized fluent, hands-off, and multi-tag tangible interactions by leveraging gravity and anti-collision physical constraints, which support effortless user input and maximize throughput. Furthermore, our system provides hot-swappable interactivity that enables smooth transitions throughout extended use. Based on the design parameters explored through a series of studies, we present a design space with proof-of-concept implementations in various applications. },
155 | booktitle = {Proceedings of the 2021 CHI Conference on Human Factors in Computing Systems},
156 | articleno = {505},
157 | numpages = {14},
158 | keywords = {Tags, Rich-ID, Motion Sensing, Fluent, Tangible Interaction, Physical Constraints, NFC},
159 | location = {Yokohama, Japan},
160 | series = {CHI '21}
161 | }
162 | ```
163 |
164 | ## License (GNU GPLv3 copyleft license)
165 | OpenNFCSense is an open-source software under the terms of **GNU GPLv3 copyleft license**. Anyone can use this, for any purpose. Since a **copyleft** license requires that the project developed around your software be distributed under the same (or similar) license, you must give all users of your work the freedom to carry out all of copying, distribution and modification activities if the work is based on OpenNFCSense.
166 |
167 | We also offer closed-source license which give you the ability not redistribute your software as open-source too. Contact the authors via (r.liang@tue.nl) if you are interested.
168 |
169 | In any form of copying, distribution and modification, you must include the following description in your source code, as mentioned in https://www.gnu.org/licenses/
170 |
171 | ```
172 | /*==========================================================================
173 | // OpenNFCSense4P (v1) - Open NFCSense API for Processing Language
174 | // Copyright (C) 2021 Dr. Rong-Hao Liang
175 | // This program is free software: you can redistribute it and/or modify
176 | // it under the terms of the GNU General Public License as published by
177 | // the Free Software Foundation, either version 3 of the License, or
178 | // (at your option) any later version.
179 | //
180 | // This program is distributed in the hope that it will be useful,
181 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
182 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
183 | // GNU General Public License for more details.
184 | //
185 | // You should have received a copy of the GNU General Public License
186 | // along with this program. If not, see .
187 | //==========================================================================*/
188 | ```
189 |
190 |
--------------------------------------------------------------------------------
/arduino/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/arduino/.DS_Store
--------------------------------------------------------------------------------
/arduino/NFCSense4P_ArduinoUno_RC522_v1/NFCSense4P_ArduinoUno_RC522_v1.ino:
--------------------------------------------------------------------------------
1 | //*********************************************
2 | // Arduino Codes for NFCSense, which is based on
3 | // - NXP MFRC522 NFC/RFID Reader (e.g., RFID RC522)
4 | // - RFID.cpp Library (created by Dr. Leong and Miguel Balboa)
5 | // for further information please check
6 | // our website: https://ronghaoliang.page/NFCSense
7 | // or contact Dr. Rong-Hao Liang (TU Eindhoven) via r.liang@tue.nl
8 | //*********************************************
9 | //Copyright <2021> Dr. Rong-Hao Liang
10 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
11 | //INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12 | //IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
13 | //WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
14 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15 |
16 | #include
17 | #include "RFID.h"
18 | #define SS_PIN 10
19 | #define RST_PIN 9
20 | #define UID_BYTEBUM 4 //The 4-Byte UID
21 |
22 | #define REFRESH_RATE 300 //unit: Hz
23 | //Recommended parameters: 300 for Arduino Uno and Leonardo, 250 for ESP32, 200 for Teensy 3.2
24 |
25 | RFID rfid(SS_PIN, RST_PIN);
26 | int UID[UID_BYTEBUM]; //UID: Unique IDentifier
27 | char dataID[UID_BYTEBUM] = {'A','B','C','D'}; //data label
28 | long timer = micros(); //timer
29 |
30 | void setup()
31 | {
32 | Serial.begin(115200);
33 | SPI.begin();
34 | rfid.init();
35 | for (int i = 0 ; i < UID_BYTEBUM ; i++) UID[i] = -1;
36 | }
37 |
38 | void loop()
39 | {
40 | if (micros() - timer >= (1000000/REFRESH_RATE) ) { //Timer: send sensor data in every 10ms
41 | timer = micros();
42 | if (rfid.isCard()) { // A tag is detected
43 | if (rfid.readCardSerial()) { // Read the tag's ID
44 | for (int i = 0 ; i < UID_BYTEBUM ; i++) UID[i] = rfid.serNum[i];
45 | }
46 | }
47 | else { // No tag is detected.
48 | for (int i = 0 ; i < UID_BYTEBUM ; i++) UID[i] = 256; //256: absence
49 | }
50 | #if PRINT_IN_SERIAL_PLOTTER
51 | printInSerialPlotter(UID);
52 | #else
53 | for (int i = 0 ; i < UID_BYTEBUM ; i++) {
54 | sendDataToProcessing(dataID[i], UID[i]);
55 | }
56 | #endif
57 | rfid.halt(); //Halt the rfid reader
58 | }
59 | }
60 |
61 | void printInSerialPlotter(int UID[]) { //println(uid[0],uid[1],uid[2],uid[3],uid[4]);
62 | for(int i=0; i< UID_BYTEBUM; i++){
63 | Serial.print(UID[i]);
64 | (i<(UID_BYTEBUM-1) ? Serial.print(','): Serial.println());
65 | }
66 | }
67 |
68 | void sendDataToProcessing(char symbol, int data) {
69 | Serial.print(symbol); // symbol prefix of data type
70 | Serial.println(data); // the integer data with a carriage return
71 | }
72 |
--------------------------------------------------------------------------------
/arduino/NFCSense4P_ArduinoUno_RC522_v1/RFID.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * RFID.cpp - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
3 | * Based on code Dr.Leong ( WWW.B2CQSHOP.COM )
4 | * Created by Miguel Balboa, Jan, 2012.
5 | * Released into the public domain.
6 | */
7 |
8 | /******************************************************************************
9 | * Includes
10 | ******************************************************************************/
11 | #include
12 | #include "RFID.h"
13 |
14 | /******************************************************************************
15 | * User API
16 | ******************************************************************************/
17 |
18 | /**
19 | * Construct RFID
20 | * int chipSelectPin RFID /ENABLE pin
21 | */
22 | RFID::RFID(int chipSelectPin, int NRSTPD)
23 | {
24 | _chipSelectPin = chipSelectPin;
25 |
26 | pinMode(_chipSelectPin,OUTPUT); // Set digital as OUTPUT to connect it to the RFID /ENABLE pin
27 | digitalWrite(_chipSelectPin, LOW);
28 |
29 |
30 | pinMode(NRSTPD,OUTPUT); // Set digital pin, Not Reset and Power-down
31 | digitalWrite(NRSTPD, HIGH);
32 | _NRSTPD = NRSTPD;
33 | }
34 | /******************************************************************************
35 | * User API
36 | ******************************************************************************/
37 |
38 | bool RFID::isCard()
39 | {
40 | unsigned char status;
41 | unsigned char str[MAX_LEN];
42 |
43 | status = MFRC522Request(PICC_REQIDL, str);
44 | if (status == MI_OK) {
45 | return true;
46 | } else {
47 | return false;
48 | }
49 | }
50 |
51 | bool RFID::readCardSerial(){
52 |
53 | unsigned char status;
54 | unsigned char str[MAX_LEN];
55 |
56 | // Anti-colisión, devuelva el número de serie de tarjeta de 4 bytes
57 | status = anticoll(str);
58 | memcpy(serNum, str, 5);
59 |
60 | if (status == MI_OK) {
61 | return true;
62 | } else {
63 | return false;
64 | }
65 |
66 | }
67 |
68 | /******************************************************************************
69 | * Dr.Leong ( WWW.B2CQSHOP.COM )
70 | ******************************************************************************/
71 |
72 | void RFID::init()
73 | {
74 | digitalWrite(_NRSTPD,HIGH);
75 |
76 | reset();
77 |
78 | //Timer: TPrescaler*TreloadVal/6.78MHz = 24ms
79 | writeMFRC522(TModeReg, 0x80); //Tauto=1; f(Timer) = 6.78MHz/TPreScaler
80 | writeMFRC522(TPrescalerReg, 0x3E); //TModeReg[3..0] + TPrescalerReg
81 | writeMFRC522(TReloadRegL, 30);
82 | writeMFRC522(TReloadRegH, 0);
83 |
84 | writeMFRC522(TxAutoReg, 0x40); //100%ASK
85 | writeMFRC522(ModeReg, 0x3D); // CRC valor inicial de 0x6363
86 |
87 | //ClearBitMask(Status2Reg, 0x08); //MFCrypto1On=0
88 | //writeMFRC522(RxSelReg, 0x86); //RxWait = RxSelReg[5..0]
89 | writeMFRC522(RFCfgReg, 0x7F); //RxGain = 48dB
90 |
91 | antennaOn(); //Abre la antena
92 |
93 |
94 | }
95 | void RFID::reset()
96 | {
97 | writeMFRC522(CommandReg, PCD_RESETPHASE);
98 | }
99 |
100 | void RFID::writeMFRC522(unsigned char addr, unsigned char val)
101 | {
102 | digitalWrite(_chipSelectPin, LOW);
103 |
104 | //0XXXXXX0 formato de dirección
105 | SPI.transfer((addr<<1)&0x7E);
106 | SPI.transfer(val);
107 |
108 | digitalWrite(_chipSelectPin, HIGH);
109 | }
110 |
111 | void RFID::antennaOn(void)
112 | {
113 | unsigned char temp;
114 |
115 | temp = readMFRC522(TxControlReg);
116 | if (!(temp & 0x03))
117 | {
118 | setBitMask(TxControlReg, 0x03);
119 | }
120 | }
121 |
122 | /*
123 | * Read_MFRC522 Nombre de la función: Read_MFRC522
124 | * Descripción: Desde el MFRC522 leer un byte de un registro de datos
125 | * Los parámetros de entrada: addr - la dirección de registro
126 | * Valor de retorno: Devuelve un byte de datos de lectura
127 | */
128 | unsigned char RFID::readMFRC522(unsigned char addr)
129 | {
130 | unsigned char val;
131 | digitalWrite(_chipSelectPin, LOW);
132 | SPI.transfer(((addr<<1)&0x7E) | 0x80);
133 | val =SPI.transfer(0x00);
134 | digitalWrite(_chipSelectPin, HIGH);
135 | return val;
136 | }
137 |
138 | void RFID::setBitMask(unsigned char reg, unsigned char mask)
139 | {
140 | unsigned char tmp;
141 | tmp = readMFRC522(reg);
142 | writeMFRC522(reg, tmp | mask); // set bit mask
143 | }
144 |
145 | void RFID::clearBitMask(unsigned char reg, unsigned char mask)
146 | {
147 | unsigned char tmp;
148 | tmp = readMFRC522(reg);
149 | writeMFRC522(reg, tmp & (~mask)); // clear bit mask
150 | }
151 |
152 | void RFID::calculateCRC(unsigned char *pIndata, unsigned char len, unsigned char *pOutData)
153 | {
154 | unsigned char i, n;
155 |
156 | clearBitMask(DivIrqReg, 0x04); //CRCIrq = 0
157 | setBitMask(FIFOLevelReg, 0x80); //Claro puntero FIFO
158 | //Write_MFRC522(CommandReg, PCD_IDLE);
159 |
160 | //Escribir datos en el FIFO
161 | for (i=0; i MAX_LEN)
268 | {
269 | n = MAX_LEN;
270 | }
271 |
272 | //??FIFO??????? Lea los datos recibidos en el FIFO
273 | for (i=0; i anticoll
325 | * Anti-detección de colisiones, la lectura del número de serie de la tarjeta de tarjeta
326 | * @param serNum - devuelve el número de tarjeta 4 bytes de serie, los primeros 5 bytes de bytes de paridad
327 | * @return retorno exitoso MI_OK
328 | */
329 | unsigned char RFID::anticoll(unsigned char *serNum)
330 | {
331 | unsigned char status;
332 | unsigned char i;
333 | unsigned char serNumCheck=0;
334 | unsigned int unLen;
335 |
336 |
337 | //ClearBitMask(Status2Reg, 0x08); //TempSensclear
338 | //ClearBitMask(CollReg,0x80); //ValuesAfterColl
339 | writeMFRC522(BitFramingReg, 0x00); //TxLastBists = BitFramingReg[2..0]
340 |
341 | serNum[0] = PICC_ANTICOLL;
342 | serNum[1] = 0x20;
343 | status = MFRC522ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen);
344 |
345 | if (status == MI_OK)
346 | {
347 | //?????? Compruebe el número de serie de la tarjeta
348 | for (i=0; i<4; i++)
349 | {
350 | serNumCheck ^= serNum[i];
351 | }
352 | if (serNumCheck != serNum[i])
353 | {
354 | status = MI_ERR;
355 | }
356 | }
357 |
358 | //SetBitMask(CollReg, 0x80); //ValuesAfterColl=1
359 |
360 | return status;
361 | }
362 |
363 | /*
364 | * MFRC522Auth -> auth
365 | * Verificar la contraseña de la tarjeta
366 | * Los parámetros de entrada: AuthMode - Modo de autenticación de contraseña
367 | 0x60 = A 0x60 = validación KeyA
368 | 0x61 = B 0x61 = validación KeyB
369 | BlockAddr-- bloque de direcciones
370 | Sectorkey-- sector contraseña
371 | serNum--,4? Tarjeta de número de serie, 4 bytes
372 | * MI_OK Valor de retorno: el retorno exitoso MI_OK
373 | */
374 | unsigned char RFID::auth(unsigned char authMode, unsigned char BlockAddr, unsigned char *Sectorkey, unsigned char *serNum)
375 | {
376 | unsigned char status;
377 | unsigned int recvBits;
378 | unsigned char i;
379 | unsigned char buff[12];
380 |
381 | //????+???+????+???? Verifique la dirección de comandos de bloques del sector + + contraseña + número de la tarjeta de serie
382 | buff[0] = authMode;
383 | buff[1] = BlockAddr;
384 | for (i=0; i<6; i++)
385 | {
386 | buff[i+2] = *(Sectorkey+i);
387 | }
388 | for (i=0; i<4; i++)
389 | {
390 | buff[i+8] = *(serNum+i);
391 | }
392 | status = MFRC522ToCard(PCD_AUTHENT, buff, 12, buff, &recvBits);
393 |
394 | if ((status != MI_OK) || (!(readMFRC522(Status2Reg) & 0x08)))
395 | {
396 | status = MI_ERR;
397 | }
398 |
399 | return status;
400 | }
401 |
402 | /*
403 | * MFRC522Read -> read
404 | * Lectura de datos de bloque
405 | * Los parámetros de entrada: blockAddr - dirección del bloque; recvData - leer un bloque de datos
406 | * MI_OK Valor de retorno: el retorno exitoso MI_OK
407 | */
408 | unsigned char RFID::read(unsigned char blockAddr, unsigned char *recvData)
409 | {
410 | unsigned char status;
411 | unsigned int unLen;
412 |
413 | recvData[0] = PICC_READ;
414 | recvData[1] = blockAddr;
415 | calculateCRC(recvData,2, &recvData[2]);
416 | status = MFRC522ToCard(PCD_TRANSCEIVE, recvData, 4, recvData, &unLen);
417 |
418 | if ((status != MI_OK) || (unLen != 0x90))
419 | {
420 | status = MI_ERR;
421 | }
422 |
423 | return status;
424 | }
425 |
426 | /*
427 | * MFRC522Write -> write
428 | * La escritura de datos de bloque
429 | * blockAddr - dirección del bloque; WriteData - para escribir 16 bytes del bloque de datos
430 | * Valor de retorno: el retorno exitoso MI_OK
431 | */
432 | unsigned char RFID::write(unsigned char blockAddr, unsigned char *writeData)
433 | {
434 | unsigned char status;
435 | unsigned int recvBits;
436 | unsigned char i;
437 | unsigned char buff[18];
438 |
439 | buff[0] = PICC_WRITE;
440 | buff[1] = blockAddr;
441 | calculateCRC(buff, 2, &buff[2]);
442 | status = MFRC522ToCard(PCD_TRANSCEIVE, buff, 4, buff, &recvBits);
443 |
444 | if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A))
445 | {
446 | status = MI_ERR;
447 | }
448 |
449 | if (status == MI_OK)
450 | {
451 | for (i=0; i<16; i++) //?FIFO?16Byte?? Datos a la FIFO 16Byte escribir
452 | {
453 | buff[i] = *(writeData+i);
454 | }
455 | calculateCRC(buff, 16, &buff[16]);
456 | status = MFRC522ToCard(PCD_TRANSCEIVE, buff, 18, buff, &recvBits);
457 |
458 | if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A))
459 | {
460 | status = MI_ERR;
461 | }
462 | }
463 |
464 | return status;
465 | }
466 |
467 |
468 | /*
469 | * MFRC522Halt -> halt
470 | * Cartas de Mando para dormir
471 | * Los parámetros de entrada: Ninguno
472 | * Valor devuelto: Ninguno
473 | */
474 | void RFID::halt()
475 | {
476 | unsigned char status;
477 | unsigned int unLen;
478 | unsigned char buff[4];
479 |
480 | buff[0] = PICC_HALT;
481 | buff[1] = 0;
482 | calculateCRC(buff, 2, &buff[2]);
483 |
484 | status = MFRC522ToCard(PCD_TRANSCEIVE, buff, 4, buff,&unLen);
485 | }
486 |
--------------------------------------------------------------------------------
/arduino/NFCSense4P_ArduinoUno_RC522_v1/RFID.h:
--------------------------------------------------------------------------------
1 | /* RFID.h - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
2 | * Based on code Dr.Leong ( WWW.B2CQSHOP.COM )
3 | * Created by Miguel Balboa (circuitito.com), Jan, 2012.
4 | */
5 | #ifndef RFID_h
6 | #define RFID_h
7 |
8 | #include
9 | #include
10 |
11 | /******************************************************************************
12 | * Definitions
13 | ******************************************************************************/
14 | #define MAX_LEN 16 // Largo m·ximo de la matriz
15 |
16 | //MF522 comando palabra
17 | #define PCD_IDLE 0x00 // NO action; Y cancelar el comando
18 | #define PCD_AUTHENT 0x0E // autenticaciÛn de clave
19 | #define PCD_RECEIVE 0x08 // recepciÛn de datos
20 | #define PCD_TRANSMIT 0x04 // Enviar datos
21 | #define PCD_TRANSCEIVE 0x0C // Enviar y recibir datos
22 | #define PCD_RESETPHASE 0x0F // reajustar
23 | #define PCD_CALCCRC 0x03 // CRC calcular
24 |
25 | //Mifare_One Tarjeta Mifare_One comando palabra
26 | #define PICC_REQIDL 0x26 // ¡rea de la antena no est· tratando de entrar en el estado de reposo
27 | #define PICC_REQALL 0x52 // Todas las cartas para encontrar el ·rea de la antena
28 | #define PICC_ANTICOLL 0x93 // anti-colisiÛn
29 | #define PICC_SElECTTAG 0x93 // elecciÛn de tarjeta
30 | #define PICC_AUTHENT1A 0x60 // verificaciÛn key A
31 | #define PICC_AUTHENT1B 0x61 // verificaciÛn Key B
32 | #define PICC_READ 0x30 // leer bloque
33 | #define PICC_WRITE 0xA0 // Escribir en el bloque
34 | #define PICC_DECREMENT 0xC0 // cargo
35 | #define PICC_INCREMENT 0xC1 // recargar
36 | #define PICC_RESTORE 0xC2 // Transferencia de datos de bloque de buffer
37 | #define PICC_TRANSFER 0xB0 // Guardar los datos en el b˙fer
38 | #define PICC_HALT 0x50 // inactividad
39 |
40 | //MF522 CÛdigo de error de comunicaciÛn cuando regresÛ
41 | #define MI_OK 0
42 | #define MI_NOTAGERR 1
43 | #define MI_ERR 2
44 |
45 | //------------------ MFRC522 registro---------------
46 | //Page 0:Command and Status
47 | #define Reserved00 0x00
48 | #define CommandReg 0x01
49 | #define CommIEnReg 0x02
50 | #define DivlEnReg 0x03
51 | #define CommIrqReg 0x04
52 | #define DivIrqReg 0x05
53 | #define ErrorReg 0x06
54 | #define Status1Reg 0x07
55 | #define Status2Reg 0x08
56 | #define FIFODataReg 0x09
57 | #define FIFOLevelReg 0x0A
58 | #define WaterLevelReg 0x0B
59 | #define ControlReg 0x0C
60 | #define BitFramingReg 0x0D
61 | #define CollReg 0x0E
62 | #define Reserved01 0x0F
63 | //Page 1:Command
64 | #define Reserved10 0x10
65 | #define ModeReg 0x11
66 | #define TxModeReg 0x12
67 | #define RxModeReg 0x13
68 | #define TxControlReg 0x14
69 | #define TxAutoReg 0x15
70 | #define TxSelReg 0x16
71 | #define RxSelReg 0x17
72 | #define RxThresholdReg 0x18
73 | #define DemodReg 0x19
74 | #define Reserved11 0x1A
75 | #define Reserved12 0x1B
76 | #define MifareReg 0x1C
77 | #define Reserved13 0x1D
78 | #define Reserved14 0x1E
79 | #define SerialSpeedReg 0x1F
80 | //Page 2:CFG
81 | #define Reserved20 0x20
82 | #define CRCResultRegM 0x21
83 | #define CRCResultRegL 0x22
84 | #define Reserved21 0x23
85 | #define ModWidthReg 0x24
86 | #define Reserved22 0x25
87 | #define RFCfgReg 0x26
88 | #define GsNReg 0x27
89 | #define CWGsPReg 0x28
90 | #define ModGsPReg 0x29
91 | #define TModeReg 0x2A
92 | #define TPrescalerReg 0x2B
93 | #define TReloadRegH 0x2C
94 | #define TReloadRegL 0x2D
95 | #define TCounterValueRegH 0x2E
96 | #define TCounterValueRegL 0x2F
97 | //Page 3:TestRegister
98 | #define Reserved30 0x30
99 | #define TestSel1Reg 0x31
100 | #define TestSel2Reg 0x32
101 | #define TestPinEnReg 0x33
102 | #define TestPinValueReg 0x34
103 | #define TestBusReg 0x35
104 | #define AutoTestReg 0x36
105 | #define VersionReg 0x37
106 | #define AnalogTestReg 0x38
107 | #define TestDAC1Reg 0x39
108 | #define TestDAC2Reg 0x3A
109 | #define TestADCReg 0x3B
110 | #define Reserved31 0x3C
111 | #define Reserved32 0x3D
112 | #define Reserved33 0x3E
113 | #define Reserved34 0x3F
114 | //-----------------------------------------------
115 |
116 | class RFID
117 | {
118 | public:
119 | RFID(int chipSelectPin, int NRSTPD);
120 |
121 | bool isCard();
122 | bool readCardSerial();
123 |
124 | void init();
125 | void reset();
126 | void writeMFRC522(unsigned char addr, unsigned char val);
127 | void antennaOn(void);
128 | unsigned char readMFRC522(unsigned char addr);
129 | void setBitMask(unsigned char reg, unsigned char mask);
130 | void clearBitMask(unsigned char reg, unsigned char mask);
131 | void calculateCRC(unsigned char *pIndata, unsigned char len, unsigned char *pOutData);
132 | unsigned char MFRC522Request(unsigned char reqMode, unsigned char *TagType);
133 | unsigned char MFRC522ToCard(unsigned char command, unsigned char *sendData, unsigned char sendLen, unsigned char *backData, unsigned int *backLen);
134 | unsigned char anticoll(unsigned char *serNum);
135 | unsigned char auth(unsigned char authMode, unsigned char BlockAddr, unsigned char *Sectorkey, unsigned char *serNum);
136 | unsigned char read(unsigned char blockAddr, unsigned char *recvData);
137 | unsigned char write(unsigned char blockAddr, unsigned char *writeData);
138 | void halt();
139 |
140 | unsigned char serNum[5]; // Constante para guardar el numero de serie leido.
141 | unsigned char AserNum[5]; // Constante para guardar el numero d serie de la secion actual.
142 |
143 | private:
144 | int _chipSelectPin;
145 | int _NRSTPD;
146 |
147 | };
148 |
149 | #endif
150 |
--------------------------------------------------------------------------------
/docs/NFCSenseCheatSheet_v1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/docs/NFCSenseCheatSheet_v1.png
--------------------------------------------------------------------------------
/download/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/download/.DS_Store
--------------------------------------------------------------------------------
/download/OpenNFCSense4P-2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/download/OpenNFCSense4P-2.zip
--------------------------------------------------------------------------------
/examples/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/.DS_Store
--------------------------------------------------------------------------------
/examples/episode1/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode1/.DS_Store
--------------------------------------------------------------------------------
/examples/episode1/e1_SingleTagEFan/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode1/e1_SingleTagEFan/.DS_Store
--------------------------------------------------------------------------------
/examples/episode1/e1_SingleTagEFan/data/tagProfile.csv:
--------------------------------------------------------------------------------
1 | UID0,UID1,UID2,UID3,Label,Ttype,Mtype,L1,L2
2 | 136,4,129,153,Black spinner,2,2,0.0,0.0
3 | 136,4,8,152,Blue spinner,2,2,0.0,0.0
4 | 136,4,6,199,LED spinner,2,2,0.0,0.0
5 | 136,4,56,233,Hot wheels,2,2,0.0,0.0
6 | 136,4,145,150,E-fan,2,2,0.0,0.0
7 | 249,34,56,174,E-fan,2,2,0.0,0.0
--------------------------------------------------------------------------------
/examples/episode1/e1_SingleTagEFan/e1_SingleTagEFan.pde:
--------------------------------------------------------------------------------
1 | /*==========================================================================
2 | // OpenNFCSense4P (v2) - Open NFCSense API for Processing Language
3 | // Copyright (C) 2021 Dr. Rong-Hao Liang
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //==========================================================================*/
17 | // e1_SingleTagRotation.pde:
18 | // This software works with a microcontroller running Arduino code and connected to an RC522 NFC/RFID Reader
19 | // OpenNFCSense API Github repository: https://github.com/howieliang/OpenNFCSense
20 | // NFCSense Project website: https://ronghaoliang.page/NFCSense/
21 |
22 | import processing.serial.*;
23 | import OpenNFCSense4P.*;
24 | Serial port;
25 | OpenNFCSense4P nfcs;
26 |
27 | String lastString = "";
28 | float lastFreq = 0;
29 | long timer = 0;
30 | float[] lastFreqArray = new float[9];
31 |
32 | float[] pushValue(float[] array, float v){
33 | float[] _array = new float[array.length];
34 | arrayCopy(array,_array);
35 | for(int i = 0; i < _array.length-1; i++){
36 | _array[i+1] = array[i];
37 | }
38 | _array[0] = v;
39 | return _array;
40 | }
41 | float medianFilter(float[] array){
42 | float[] _array = new float[array.length];
43 | arrayCopy(array,_array);
44 | _array=sort(_array);
45 | println(_array);
46 | return _array[floor(_array.length/2)];
47 | }
48 |
49 | void setup() {
50 | size(800, 600, P2D); //Start a 800x600 px canvas (using P2D renderer)
51 | nfcs = new OpenNFCSense4P(this, "tagProfile.csv"); //Initialize OpenNFCSense with the tag profiles (*.csv) in /data
52 | //nfcs = new OpenNFCSense4P(this, "demo.csv", 250, 500, 2000);
53 | ////set frame rate to 250fps, TTL timer1 to 500ms, and TTL timer2 to 2000ms
54 | initSerial(); //Initialize the serial port
55 | /*== Put your codes below ==*/
56 | timer = millis()-7000;
57 | /*== Put your codes above ==*/
58 | }
59 |
60 | void draw() {
61 | nfcs.updateNFCBits(); //update the features of current bit
62 | /*== Put your codes below ==*/
63 | ArrayList nbitList = nfcs.getNFCBits();
64 | if (nbitList.size()>0) {
65 | String s = nbitList.get(0).getName();
66 | if (lastString != s) {
67 | lastString = s;
68 | }
69 | if (lastString.equals("E-fan")){
70 | lastFreqArray=pushValue(lastFreqArray, nbitList.get(0).getFrequency());
71 | lastFreq = medianFilter(lastFreqArray);
72 | }
73 | timer = millis();
74 | }
75 | println(lastString);
76 | /*== Put your codes above ==*/
77 | background(255); //Refresh the screen
78 | nfcs.drawMotionModeRecords(50, 2*height/3, 2*width/3, height/3-50); //draw the motion mode record of last second (x,y,width,height)
79 |
80 | drawLastBit(50, 100); //print the extra information of the last NFCBit in the console
81 | /*== Put your codes below ==*/
82 | if (millis()-timer<1000) {
83 | if (lastString.equals("E-fan")) {
84 | if (lastFreq > 52) {
85 | drawString("Full Speed: 15-20 mins left", 50, height/4+100);
86 | } else if (lastFreq > 40 && lastFreq <= 52) {
87 | drawString("Mid Speed: 20-25 mins left", 50, height/4+100);
88 | } else if (lastFreq > 25 && lastFreq <= 40) {
89 | drawString("Low Speed: 25-30 mins left", 50, height/4+100);
90 | } else if (lastFreq <= 25 && lastFreq > 2) {
91 | drawString("...", 50, height/4+100);
92 | } else {
93 | drawString("Off.", 50, height/4+100);
94 | }
95 | }
96 | } else {
97 | if (lastString == "E-fan") {
98 | drawString("Off.", 50, height/4+100);
99 | }
100 | }
101 | /*== Put your codes above ==*/
102 | //drawRecentBits(50, height/4+100); //draw the basic information of the recent NFCBits (within Timer2)
103 | drawInfo(width, height); //draw the version, read rate, and TTL timer info
104 | //printLastBit(); //print the extra information of the last NFCBit in the console
105 | //printCurrentTag(); //print the current tag read by the reader
106 | }
107 |
108 | /*Initialize the serial port*/
109 | void initSerial() {
110 | for (int i = 0; i < Serial.list().length; i++) println("[", i, "]:", Serial.list()[i]); //print the serial port
111 | port = new Serial(this, Serial.list()[Serial.list().length-1], 115200); //for Mac and Linux
112 | // port = new Serial(this, Serial.list()[0], 115200); // for PC
113 | port.bufferUntil('\n'); // arduino ends each data packet with a carriage return
114 | port.clear(); // flush the Serial buffer
115 | }
116 |
117 | /*draw a formatted String*/
118 | void drawString(String s, int x, int y) { //print the latest tag appearance
119 | pushStyle();
120 | fill(0);
121 | textSize(48);
122 | text(s, x, y);
123 | popStyle();
124 | }
125 |
126 | /*draw the basic information of the last NFCBit*/
127 | void drawLastBit(int x, int y) { //print the latest tag appearance
128 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
129 | String objInfo = "Current object: ", motionInfo = "";
130 | String tagID = "";
131 | if (nbitList.size()>0) {
132 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
133 | tagID = "["+nfcs.getIDTable().get(0)+"]"; // get the ID string of the latest tag
134 | objInfo += nb.getName();
135 | if (nb.getMode()!=NFCBit.NA) { // if the feature is ready (mode!=NA=0)
136 | if (nb.isFrequency()) { // if the NFCBit is a frequency bit
137 | motionInfo += nb.getModeString()+" at "+nf(nb.getFrequency(), 0, 2)+" Hz"; //show the motion mode and the motion frequency
138 | } else {
139 | motionInfo += nb.getModeString()+" at "+nf(nb.getSpeed(), 0, 2)+" km/h"; //show the motion mode and the motion speed
140 | }
141 | }
142 | }
143 | pushStyle();
144 | fill(0);
145 | textSize(48);
146 | text(objInfo, x, y);
147 | textSize(32);
148 | text(motionInfo, x, y+48);
149 | textSize(16);
150 | text(tagID, x, y+48+32);
151 | popStyle();
152 | }
153 |
154 | /*draw the basic information of the recent NFCBits (within timer 2)*/
155 | void drawRecentBits(int x, int y) {
156 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
157 | ArrayList IDList = nfcs.getIDTable(); // get the ID string of the recent NFCBits
158 | String tagName = "";
159 | String tagID = "";
160 | //for (int i = 0; i < nbitList.size(); i++) { // to reverse the order
161 | for (int i = nbitList.size()-1; i >=0; i--) {
162 | NFCBit nb = nbitList.get(i);
163 | tagName += nb.getName();
164 | tagID += "["+IDList.get(i)+"]";
165 | if (i>0) {
166 | tagName += ", ";
167 | tagID += ", ";
168 | }
169 | }
170 | pushStyle();
171 | fill(0);
172 | textSize(48);
173 | text("Recent objects: ", x, y);
174 | textSize(32);
175 | text(tagName, x, y+48);
176 | textSize(16);
177 | text(tagID, x, y+48+32);
178 | popStyle();
179 | }
180 |
181 | /*draw the version, read rate, and TTL timer info*/
182 | void drawInfo(int x, int y) {
183 | String info = "[Open NFCSense] ver. "+OpenNFCSense4P.version()+"\n"; //get the current library version
184 | info += "Read rate: "+nf(nfcs.getReadRate(), 0, 0)+" reads/sec\n"; // get the current read rate
185 | info += "TTL Timer1: "+nf(nfcs.getTimer1(), 0, 0)+" ms\n"; // get the current TTL timer1
186 | info += "TTL Timer2: "+nf(nfcs.getTimer2(), 0, 0)+" ms"; // get the current TTL timer2
187 | //set the above parameters in the constructor as indicated in setup();
188 | pushStyle();
189 | fill(100);
190 | textSize(12);
191 | textAlign(RIGHT, BOTTOM);
192 | text(info, x-5, y-5);
193 | popStyle();
194 | }
195 |
196 | /*print the extra information of the recent NFCBits in the console*/
197 | void printRecentBits() {
198 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
199 | for (int i = 0; i < nbitList.size(); i++) {
200 | NFCBit nb = nbitList.get(i); // get the latest NFCBit at index i
201 | String tagID = "["+nfcs.getIDTable().get(i)+"]"; //get the ID string of the latest tag
202 | print("[", i, "]", tagID, nb.getName(), ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
203 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
204 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
205 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
206 | //the type of motion (e.g., linear translation, rotation, shm, compound+motion)
207 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
208 | //the features (speed and frequency)
209 | }
210 | println("===");
211 | }
212 |
213 | /*print the extra information of the last NFCBit in the console*/
214 | void printLastBit() {
215 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
216 | if (nbitList.size()>0) {
217 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
218 | String tagID = "["+nfcs.getIDTable().get(0)+"]"; //get the ID string of the latest tag
219 | print(nb.getName(), tagID, ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
220 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
221 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
222 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
223 | //the type of motion (e.g., linear translation, rotation, shm, compound, compound+motion)
224 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
225 | //the features (speed and frequency)
226 | }
227 | println("===");
228 | }
229 |
230 | /*The serial event handler processes the data from any NFC reader in the String format of
231 | // "A[Byte_0]\n, B[Byte_1]\n, C[Byte_2]\n, or D[Byte_3]\n",
232 | //where every byte is an unsigned integer ranged between [0-256].
233 | //When a tag is present: Byte_i=[0-255]; Otherwise, when a tag is absent: [256].
234 | //================*/
235 |
236 | void serialEvent(Serial port) {
237 | String inData = port.readStringUntil('\n'); // read the serial string until seeing a carriage return
238 | if (inData.charAt(0) >= 'A' && inData.charAt(0) <= 'D') {
239 | int i = inData.charAt(0)-'A';
240 | int v = int(trim(inData.substring(1)));
241 | nfcs.rfid[i] = (v>255?-1:v);
242 | if (i==3) nfcs.checkTagID(); // process the tag ID when a sequence is collected completely.
243 | }
244 | return;
245 | }
246 |
247 | //print the current tag read by the reader
248 | void printCurrentTag() {
249 | if (nfcs.rfid[0]<0) println("No tag");
250 | else println(nfcs.rfid[0], ",", nfcs.rfid[1], ",", nfcs.rfid[2], ",", nfcs.rfid[3]);
251 | }
252 |
--------------------------------------------------------------------------------
/examples/episode1/e1_SingleTagRoulette/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode1/e1_SingleTagRoulette/.DS_Store
--------------------------------------------------------------------------------
/examples/episode1/e1_SingleTagRoulette/data/tagProfile.csv:
--------------------------------------------------------------------------------
1 | UID0,UID1,UID2,UID3,Label,Ttype,Mtype,L1,L2
2 | 136,4,129,153,Black spinner,2,2,0.0,0.0
3 | 169,225,55,174,Papa John's,2,2,0.0,0.0
4 | 249,34,56,174,Domino's,2,2,0.0,0.0
5 | 9,121,66,174,Pizza hut,2,2,0.0,0.0
6 | 41,245,68,174,Tim Hortons,2,2,0.0,0.0
7 | 57,96,60,174,Starbucks,2,2,0.0,0.0
8 | 9,186,63,174,Subway,2,2,0.0,0.0
9 | 217,17,62,174,Burger king,2,2,0.0,0.0
10 | 57,78,56,174,KFC,2,2,0.0,0.0
11 | 233,196,65,174,Taco bell,2,2,0.0,0.0
12 | 249,140,70,174,Macdonld's,2,2,0.0,0.0
13 | 201,25,70,174,Panda exp,2,2,0.0,0.0
14 | 233,24,55,174,Wendy's,2,2,0.0,0.0
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/episode1/e1_SingleTagRoulette/e1_SingleTagRoulette.pde:
--------------------------------------------------------------------------------
1 | /*==========================================================================
2 | // OpenNFCSense4P (v2) - Open NFCSense API for Processing Language
3 | // Copyright (C) 2021 Dr. Rong-Hao Liang
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //==========================================================================*/
17 | // e1_SingleTagRotation.pde:
18 | // This software works with a microcontroller running Arduino code and connected to an RC522 NFC/RFID Reader
19 | // OpenNFCSense API Github repository: https://github.com/howieliang/OpenNFCSense
20 | // NFCSense Project website: https://ronghaoliang.page/NFCSense/
21 |
22 | import processing.serial.*;
23 | import OpenNFCSense4P.*;
24 | Serial port;
25 | OpenNFCSense4P nfcs;
26 |
27 | String lastString = "";
28 | long timer = 0;
29 |
30 | void setup() {
31 | size(800, 600, P2D); //Start a 800x600 px canvas (using P2D renderer)
32 | nfcs = new OpenNFCSense4P(this, "tagProfile.csv"); //Initialize OpenNFCSense with the tag profiles (*.csv) in /data
33 | //nfcs = new OpenNFCSense4P(this, "demo.csv", 250, 500, 2000);
34 | ////set frame rate to 250fps, TTL timer1 to 500ms, and TTL timer2 to 2000ms
35 | initSerial(); //Initialize the serial port
36 | /*== Put your codes below ==*/
37 | timer = millis()-7000;
38 | /*== Put your codes above ==*/
39 | }
40 |
41 | void draw() {
42 | nfcs.updateNFCBits(); //update the features of current bit
43 | /*== Put your codes below ==*/
44 | ArrayList nbitList = nfcs.getNFCBits();
45 | if(nbitList.size()>0){
46 | String s = nbitList.get(0).getName();
47 | if(lastString != s){
48 | lastString = s;
49 | timer = millis();
50 | }
51 | }
52 |
53 | /*== Put your codes above ==*/
54 | background(255); //Refresh the screen
55 | nfcs.drawMotionModeRecords(50, 2*height/3, 2*width/3, height/3-50); //draw the motion mode record of last second (x,y,width,height)
56 | /*== Put your codes below ==*/
57 | if(millis()-timer<1000){
58 | //drawLastBit(50,100); //print the extra information of the last NFCBit in the console
59 | drawRecentBits(50, height/4+100); //draw the basic information of the recent NFCBits (within Timer2)
60 | }else{
61 | if(millis()-timer<7000){
62 | drawString("Calling: "+lastString+" ...",50,100);
63 | }else{
64 | drawString("Dash Roulette",50,100);
65 | }
66 | }
67 | /*== Put your codes above ==*/
68 | drawInfo(width, height); //draw the version, read rate, and TTL timer info
69 | //printLastBit(); //print the extra information of the last NFCBit in the console
70 | printCurrentTag(); //print the current tag read by the reader
71 | }
72 |
73 | /*Initialize the serial port*/
74 | void initSerial() {
75 | for (int i = 0; i < Serial.list().length; i++) println("[", i, "]:", Serial.list()[i]); //print the serial port
76 | port = new Serial(this, Serial.list()[Serial.list().length-1], 115200); //for Mac and Linux
77 | // port = new Serial(this, Serial.list()[0], 115200); // for PC
78 | port.bufferUntil('\n'); // arduino ends each data packet with a carriage return
79 | port.clear(); // flush the Serial buffer
80 | }
81 |
82 | /*draw a formatted String*/
83 | void drawString(String s, int x, int y) { //print the latest tag appearance
84 | pushStyle();
85 | fill(0);
86 | textSize(48);
87 | text(s, x, y);
88 | popStyle();
89 | }
90 |
91 | /*draw the basic information of the last NFCBit*/
92 | void drawLastBit(int x, int y) { //print the latest tag appearance
93 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
94 | String objInfo = "Current object: ", motionInfo = "";
95 | String tagID = "";
96 | if (nbitList.size()>0) {
97 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
98 | tagID = "["+nfcs.getIDTable().get(0)+"]"; // get the ID string of the latest tag
99 | objInfo += nb.getName();
100 | if (nb.getMode()!=NFCBit.NA) { // if the feature is ready (mode!=NA=0)
101 | if (nb.isFrequency()) { // if the NFCBit is a frequency bit
102 | motionInfo += nb.getModeString()+" at "+nf(nb.getFrequency(), 0, 2)+" Hz"; //show the motion mode and the motion frequency
103 | } else {
104 | motionInfo += nb.getModeString()+" at "+nf(nb.getSpeed(), 0, 2)+" km/h"; //show the motion mode and the motion speed
105 | }
106 | }
107 | }
108 | pushStyle();
109 | fill(0);
110 | textSize(48);
111 | text(objInfo, x, y);
112 | textSize(32);
113 | text(motionInfo, x, y+48);
114 | textSize(16);
115 | text(tagID, x, y+48+32);
116 | popStyle();
117 | }
118 |
119 | /*draw the basic information of the recent NFCBits (within timer 2)*/
120 | void drawRecentBits(int x, int y){
121 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
122 | ArrayList IDList = nfcs.getIDTable(); // get the ID string of the recent NFCBits
123 | String tagName = "";
124 | String tagID = "";
125 | for (int i = 0; i < nbitList.size(); i++) { // to reverse the order
126 | //for (int i = nbitList.size()-1; i >=0; i--) {
127 | NFCBit nb = nbitList.get(i);
128 | tagName += nb.getName();
129 | tagID += "["+IDList.get(i)+"]";
130 | //if (i>0){
131 | tagName += ", ";
132 | tagID += ", ";
133 | //}
134 | }
135 | pushStyle();
136 | fill(0);
137 | textSize(48);
138 | text("Recent objects: ", x, y);
139 | textSize(32);
140 | text(tagName, x, y+48);
141 | textSize(16);
142 | text(tagID, x, y+48+32);
143 | popStyle();
144 | }
145 |
146 | /*draw the version, read rate, and TTL timer info*/
147 | void drawInfo(int x, int y) {
148 | String info = "[Open NFCSense] ver. "+OpenNFCSense4P.version()+"\n"; //get the current library version
149 | info += "Read rate: "+nf(nfcs.getReadRate(),0,0)+" reads/sec\n"; // get the current read rate
150 | info += "TTL Timer1: "+nf(nfcs.getTimer1(),0,0)+" ms\n"; // get the current TTL timer1
151 | info += "TTL Timer2: "+nf(nfcs.getTimer2(),0,0)+" ms"; // get the current TTL timer2
152 | //set the above parameters in the constructor as indicated in setup();
153 | pushStyle();
154 | fill(100);
155 | textSize(12);
156 | textAlign(RIGHT,BOTTOM);
157 | text(info, x-5, y-5);
158 | popStyle();
159 | }
160 |
161 | /*print the extra information of the recent NFCBits in the console*/
162 | void printRecentBits() {
163 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
164 | for (int i = 0; i < nbitList.size(); i++) {
165 | NFCBit nb = nbitList.get(i); // get the latest NFCBit at index i
166 | String tagID = "["+nfcs.getIDTable().get(i)+"]"; //get the ID string of the latest tag
167 | print("[", i, "]",tagID, nb.getName(), ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
168 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
169 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
170 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
171 | //the type of motion (e.g., linear translation, rotation, shm, compound+motion)
172 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
173 | //the features (speed and frequency)
174 | }
175 | println("===");
176 | }
177 |
178 | /*print the extra information of the last NFCBit in the console*/
179 | void printLastBit() {
180 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
181 | if (nbitList.size()>0) {
182 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
183 | String tagID = "["+nfcs.getIDTable().get(0)+"]"; //get the ID string of the latest tag
184 | print(nb.getName(), tagID,":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
185 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
186 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
187 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
188 | //the type of motion (e.g., linear translation, rotation, shm, compound, compound+motion)
189 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
190 | //the features (speed and frequency)
191 | }
192 | println("===");
193 | }
194 |
195 | /*The serial event handler processes the data from any NFC reader in the String format of
196 | // "A[Byte_0]\n, B[Byte_1]\n, C[Byte_2]\n, or D[Byte_3]\n",
197 | //where every byte is an unsigned integer ranged between [0-256].
198 | //When a tag is present: Byte_i=[0-255]; Otherwise, when a tag is absent: [256].
199 | //================*/
200 |
201 | void serialEvent(Serial port) {
202 | String inData = port.readStringUntil('\n'); // read the serial string until seeing a carriage return
203 | if (inData.charAt(0) >= 'A' && inData.charAt(0) <= 'D') {
204 | int i = inData.charAt(0)-'A';
205 | int v = int(trim(inData.substring(1)));
206 | nfcs.rfid[i] = (v>255?-1:v);
207 | if(i==3) nfcs.checkTagID(); // process the tag ID when a sequence is collected completely.
208 | }
209 | return;
210 | }
211 |
212 | //print the current tag read by the reader
213 | void printCurrentTag(){
214 | if(nfcs.rfid[0]<0 || nfcs.rfid[1]<0 || nfcs.rfid[2]<0 || nfcs.rfid[3]<0) println("No tag");
215 | else println(nfcs.rfid[0],",",nfcs.rfid[1],",",nfcs.rfid[2],",",nfcs.rfid[3]);
216 | }
217 |
--------------------------------------------------------------------------------
/examples/episode1/e1_SingleTagWheel/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode1/e1_SingleTagWheel/.DS_Store
--------------------------------------------------------------------------------
/examples/episode1/e1_SingleTagWheel/data/tagProfile.csv:
--------------------------------------------------------------------------------
1 | UID0,UID1,UID2,UID3,Label,Ttype,Mtype,L1,L2
2 | 136,4,129,153,Black spinner,2,2,0.0,0.0
3 | 136,4,8,152,Blue spinner,2,2,0.0,0.0
4 | 136,4,6,199,LED spinner,2,2,0.0,0.0
5 | 136,4,56,233,Hot wheels,2,2,0.0,0.0
6 | 136,4,145,150,E-fan,2,2,0.0,0.0
7 | 136,4,87,200,A,2,1,0.0,0.0
8 | 136,4,72,200,B,2,1,0.0,0.0
9 | 136,4,232,199,C,2,1,0.0,0.0
10 | 136,4,237,199,D,2,1,0.0,0.0
11 | 136,4,21,199,E,2,1,0.0,0.0
12 | 136,4,53,200,F,2,1,0.0,0.0
13 | 136,4,1,199,G,2,1,0.0,0.0
14 | 136,4,58,200,H,2,1,0.0,0.0
15 | 136,4,52,200,I,2,1,0.0,0.0
16 | 136,4,68,200,J,2,1,0.0,0.0
17 | 136,4,16,199,K,2,1,0.0,0.0
18 | 136,4,47,200,L,2,1,0.0,0.0
19 | 136,4,222,199,M,2,1,0.0,0.0
20 | 136,4,242,199,N,2,1,0.0,0.0
21 | 136,4,63,200,O,2,1,0.0,0.0
22 | 136,4,252,199,P,2,1,0.0,0.0
23 | 136,4,77,200,Q,2,1,0.0,0.0
24 | 136,4,227,199,R,2,1,0.0,0.0
25 | 136,4,92,200,S,2,1,0.0,0.0
26 | 136,4,48,200,T,2,1,0.0,0.0
27 | 136,4,247,199,U,2,1,0.0,0.0
28 | 136,4,27,200,V,2,1,0.0,0.0
29 | 136,4,82,200,W,2,1,0.0,0.0
30 | 136,4,31,199,X,2,1,0.0,0.0
31 | 136,4,37,200,Y,2,1,0.0,0.0
32 | 136,4,26,199,Z,2,1,0.0,0.0
33 | 136,4,129,200,0,2,1,0.0,0.0
34 | 136,4,32,200,1,2,1,0.0,0.0
35 | 136,4,126,199,2,2,1,0.0,0.0
36 | 136,4,111,199,3,2,1,0.0,0.0
37 | 136,4,121,199,4,2,1,0.0,0.0
38 | 136,4,116,199,5,2,1,0.0,0.0
39 | 136,4,101,199,6,2,1,0.0,0.0
40 | 136,4,91,199,7,2,1,0.0,0.0
41 | 136,4,96,199,8,2,1,0.0,0.0
42 | 136,4,106,199,9,2,1,0.0,0.0
43 | 136,4,107,200,Apple,2,1,0.0,0.0
44 | 136,4,112,200,2,2,1,0.0,0.0
45 | 136,4,117,200,Carrot,2,1,0.0,0.0
46 | 136,4,22,200,1,2,1,0.0,0.0
47 | 136,4,36,199,3,2,1,0.0,0.0
48 | 136,4,102,200,Banana,2,1,0.0,0.0
--------------------------------------------------------------------------------
/examples/episode1/e1_SingleTagWheel/e1_SingleTagWheel.pde:
--------------------------------------------------------------------------------
1 | /*==========================================================================
2 | // OpenNFCSense4P (v2) - Open NFCSense API for Processing Language
3 | // Copyright (C) 2021 Dr. Rong-Hao Liang
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //==========================================================================*/
17 | // e1_SingleTagRotation.pde:
18 | // This software works with a microcontroller running Arduino code and connected to an RC522 NFC/RFID Reader
19 | // OpenNFCSense API Github repository: https://github.com/howieliang/OpenNFCSense
20 | // NFCSense Project website: https://ronghaoliang.page/NFCSense/
21 |
22 | import processing.serial.*;
23 | import OpenNFCSense4P.*;
24 | Serial port;
25 | OpenNFCSense4P nfcs;
26 |
27 | String lastString = "";
28 | float lastFreq = 0;
29 | long timer = 0;
30 | float[] lastFreqArray = new float[9];
31 |
32 | float temp=0;
33 | float pointerValue;
34 |
35 | float[] pushValue(float[] array, float v) {
36 | float[] _array = new float[array.length];
37 | arrayCopy(array, _array);
38 | for (int i = 0; i < _array.length-1; i++) {
39 | _array[i+1] = array[i];
40 | }
41 | _array[0] = v;
42 | return _array;
43 | }
44 | float medianFilter(float[] array) {
45 | float[] _array = new float[array.length];
46 | arrayCopy(array, _array);
47 | _array=sort(_array);
48 | println(_array);
49 | return _array[floor(_array.length/2)];
50 | }
51 |
52 | void setup() {
53 | size(800, 600, P2D); //Start a 800x600 px canvas (using P2D renderer)
54 | //nfcs = new OpenNFCSense4P(this, "tagProfile.csv"); //Initialize OpenNFCSense with the tag profiles (*.csv) in /data
55 | nfcs = new OpenNFCSense4P(this, "tagProfile.csv", 300, 300, 500);
56 | ////set frame rate to 250fps, TTL timer1 to 500ms, and TTL timer2 to 2000ms
57 | initSerial(); //Initialize the serial port
58 | /*== Put your codes below ==*/
59 | timer = millis()-7000;
60 | /*== Put your codes above ==*/
61 | }
62 |
63 | void draw() {
64 | nfcs.updateNFCBits(); //update the features of current bit
65 | /*== Put your codes below ==*/
66 | ArrayList nbitList = nfcs.getNFCBits();
67 | if (nbitList.size()>0) {
68 | String s = nbitList.get(0).getName();
69 | if (lastString != s) {
70 | lastString = s;
71 | }
72 | if (lastString.equals("E-fan")) {
73 | lastFreqArray=pushValue(lastFreqArray, nbitList.get(0).getFrequency());
74 | lastFreq = medianFilter(lastFreqArray);
75 | }
76 | if (lastString.equals("Hot wheels")){
77 | temp = nbitList.get(0).getFrequency();
78 |
79 | }
80 | timer = millis();
81 | }
82 | println(lastString);
83 | /*== Put your codes above ==*/
84 | background(255); //Refresh the screen
85 | nfcs.drawMotionModeRecords(50, 2*height/3, 2*width/3, height/3-50); //draw the motion mode record of last second (x,y,width,height)
86 |
87 | drawLastBit(50, 100); //print the extra information of the last NFCBit in the console
88 | /*== Put your codes below ==*/
89 | if (lastString.equals("E-fan")) {
90 | if (millis()-timer<1000) {
91 | if (lastFreq > 52) {
92 | drawString("Full Speed: 15-20 mins left", 50, height/4+100);
93 | } else if (lastFreq > 40 && lastFreq <= 52) {
94 | drawString("Mid Speed: 20-25 mins left", 50, height/4+100);
95 | } else if (lastFreq > 25 && lastFreq <= 40) {
96 | drawString("Low Speed: 25-30 mins left", 50, height/4+100);
97 | } else if (lastFreq <= 25 && lastFreq > 2) {
98 | drawString("Turning off...", 50, height/4+100);
99 | } else {
100 | drawString("Off.", 50, height/4+100);
101 | }
102 | } else {
103 | drawString("Off.", 50, height/4+100);
104 | }
105 | }
106 |
107 | if (lastString.equals("Hot wheels")) {
108 | if (millis()-timer>100) temp = 0;
109 | pointerValue = pointerValue*0.9 + temp*0.1;
110 | drawSpeedmeter(pointerValue, 500, 150, 200, 200, 100);
111 | }
112 | /*== Put your codes above ==*/
113 |
114 | //drawRecentBits(50, height/4+100); //draw the basic information of the recent NFCBits (within Timer2)
115 | drawInfo(width, height); //draw the version, read rate, and TTL timer info
116 | //printLastBit(); //print the extra information of the last NFCBit in the console
117 | //printCurrentTag(); //print the current tag read by the reader
118 | }
119 |
120 | /*Initialize the serial port*/
121 | void initSerial() {
122 | for (int i = 0; i < Serial.list().length; i++) println("[", i, "]:", Serial.list()[i]); //print the serial port
123 | port = new Serial(this, Serial.list()[Serial.list().length-1], 115200); //for Mac and Linux
124 | // port = new Serial(this, Serial.list()[0], 115200); // for PC
125 | port.bufferUntil('\n'); // arduino ends each data packet with a carriage return
126 | port.clear(); // flush the Serial buffer
127 | }
128 |
129 | /*draw a formatted String*/
130 | void drawString(String s, int x, int y) { //print the latest tag appearance
131 | pushStyle();
132 | fill(0);
133 | textSize(48);
134 | text(s, x, y);
135 | popStyle();
136 | }
137 |
138 | void drawSpeedmeter(float TacoValue, float _x, float _y, float _w, float _h, float _r) {
139 | float blight = 90;
140 | float r = _r;
141 | pushStyle();
142 | colorMode(HSB, 140);
143 | float TacoValueMap = map(TacoValue, 0, 30, -40, 220);
144 | float theta = radians(TacoValueMap);
145 | float x;
146 | float y;
147 | x = -r*cos(theta);
148 | y = -r*sin(theta);
149 |
150 | fill(30, 0, blight);
151 | textAlign(CENTER);
152 | textSize(50);
153 |
154 | pushMatrix();
155 | translate(_x, _y);
156 |
157 | pushMatrix();
158 | translate(_w/2, _h/2);
159 | rotate(-70 * PI / 180);
160 | strokeCap(SQUARE);
161 | strokeWeight(10);
162 | stroke(55, 99, 30);
163 | for (int i = 0; i < 7; i++) {
164 | rotate(40 * PI / 180);
165 | line(-r-10, 0, -r+33, 0);
166 | }
167 | popMatrix();
168 |
169 | pushMatrix();
170 | translate(_w/2, _h/2);
171 | rotate(-70 * PI / 180);
172 | strokeCap(ROUND);
173 | strokeWeight(8);
174 | stroke(55, 80, blight);
175 | for (int i = 0; i < 7; i++) {
176 | rotate(40 * PI / 180);
177 | line(-r-8, 0, -r+32, 0);
178 | }
179 | popMatrix();
180 |
181 | pushMatrix();
182 | translate(_w/2, _h/2);
183 | rotate(-30 * PI / 180);
184 | strokeCap(ROUND);
185 | strokeWeight(4);
186 | stroke(55, 80, blight);
187 | for (int i = 0; i < 24; i++) {
188 | rotate(10 * PI / 180);
189 | line(-r-8, 0, -r+10, 0);
190 | }
191 | popMatrix();
192 |
193 | pushMatrix();
194 | translate(_w/2, _h/2);
195 | rotate(-30 * PI / 180);
196 | strokeCap(ROUND);
197 | strokeWeight(4);
198 | stroke(55, 80, blight);
199 | for (int i = 0; i < 48; i++) {
200 | rotate(5 * PI / 180);
201 | line(-r-8, 0, -r, 0);
202 | }
203 | popMatrix();
204 |
205 | pushMatrix();
206 | translate(_w/2, _h/2);
207 | noFill();
208 | stroke(0, 0, 50);
209 | strokeWeight(15);
210 | stroke(0, 99, 30);
211 | strokeWeight(12);
212 | strokeCap(ROUND);
213 | line(0, 0, x, y);
214 | stroke(0, 99, blight);
215 | strokeWeight(8);
216 | line(0, 0, x, y);
217 | stroke(0, 0, blight);
218 | strokeWeight(6);
219 | line(x/10, y/10, x/5, y/5);
220 | popMatrix();
221 |
222 | stroke(0, 0, 30);
223 | strokeWeight(3);
224 | fill(0, 0, blight);
225 | ellipse(_w/2, _h/2, 44, 44);
226 | popMatrix();
227 | popStyle();
228 | println(TacoValueMap);
229 | }
230 |
231 | /*draw the basic information of the last NFCBit*/
232 | void drawLastBit(int x, int y) { //print the latest tag appearance
233 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
234 | String objInfo = "Current object: ", motionInfo = "";
235 | String tagID = "";
236 | if (nbitList.size()>0) {
237 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
238 | tagID = "["+nfcs.getIDTable().get(0)+"]"; // get the ID string of the latest tag
239 | objInfo += nb.getName();
240 | if (nb.getMode()!=NFCBit.NA) { // if the feature is ready (mode!=NA=0)
241 | if (nb.isFrequency()) { // if the NFCBit is a frequency bit
242 | motionInfo += nb.getModeString()+" at "+nf(nb.getFrequency(), 0, 2)+" Hz"; //show the motion mode and the motion frequency
243 | } else {
244 | motionInfo += nb.getModeString()+" at "+nf(nb.getSpeed(), 0, 2)+" km/h"; //show the motion mode and the motion speed
245 | }
246 | }
247 | }
248 | pushStyle();
249 | fill(0);
250 | textSize(48);
251 | text(objInfo, x, y);
252 | textSize(32);
253 | text(motionInfo, x, y+48);
254 | textSize(16);
255 | text(tagID, x, y+48+32);
256 | popStyle();
257 | }
258 |
259 | /*draw the basic information of the recent NFCBits (within timer 2)*/
260 | void drawRecentBits(int x, int y) {
261 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
262 | ArrayList IDList = nfcs.getIDTable(); // get the ID string of the recent NFCBits
263 | String tagName = "";
264 | String tagID = "";
265 | //for (int i = 0; i < nbitList.size(); i++) { // to reverse the order
266 | for (int i = nbitList.size()-1; i >=0; i--) {
267 | NFCBit nb = nbitList.get(i);
268 | tagName += nb.getName();
269 | tagID += "["+IDList.get(i)+"]";
270 | if (i>0) {
271 | tagName += ", ";
272 | tagID += ", ";
273 | }
274 | }
275 | pushStyle();
276 | fill(0);
277 | textSize(48);
278 | text("Recent objects: ", x, y);
279 | textSize(32);
280 | text(tagName, x, y+48);
281 | textSize(16);
282 | text(tagID, x, y+48+32);
283 | popStyle();
284 | }
285 |
286 | /*draw the version, read rate, and TTL timer info*/
287 | void drawInfo(int x, int y) {
288 | String info = "[Open NFCSense] ver. "+OpenNFCSense4P.version()+"\n"; //get the current library version
289 | info += "Read rate: "+nf(nfcs.getReadRate(), 0, 0)+" reads/sec\n"; // get the current read rate
290 | info += "TTL Timer1: "+nf(nfcs.getTimer1(), 0, 0)+" ms\n"; // get the current TTL timer1
291 | info += "TTL Timer2: "+nf(nfcs.getTimer2(), 0, 0)+" ms"; // get the current TTL timer2
292 | //set the above parameters in the constructor as indicated in setup();
293 | pushStyle();
294 | fill(100);
295 | textSize(12);
296 | textAlign(RIGHT, BOTTOM);
297 | text(info, x-5, y-5);
298 | popStyle();
299 | }
300 |
301 | /*print the extra information of the recent NFCBits in the console*/
302 | void printRecentBits() {
303 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
304 | for (int i = 0; i < nbitList.size(); i++) {
305 | NFCBit nb = nbitList.get(i); // get the latest NFCBit at index i
306 | String tagID = "["+nfcs.getIDTable().get(i)+"]"; //get the ID string of the latest tag
307 | print("[", i, "]", tagID, nb.getName(), ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
308 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
309 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
310 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
311 | //the type of motion (e.g., linear translation, rotation, shm, compound+motion)
312 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
313 | //the features (speed and frequency)
314 | }
315 | println("===");
316 | }
317 |
318 | /*print the extra information of the last NFCBit in the console*/
319 | void printLastBit() {
320 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
321 | if (nbitList.size()>0) {
322 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
323 | String tagID = "["+nfcs.getIDTable().get(0)+"]"; //get the ID string of the latest tag
324 | print(nb.getName(), tagID, ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
325 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
326 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
327 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
328 | //the type of motion (e.g., linear translation, rotation, shm, compound, compound+motion)
329 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
330 | //the features (speed and frequency)
331 | }
332 | println("===");
333 | }
334 |
335 | /*The serial event handler processes the data from any NFC reader in the String format of
336 | // "A[Byte_0]\n, B[Byte_1]\n, C[Byte_2]\n, or D[Byte_3]\n",
337 | //where every byte is an unsigned integer ranged between [0-256].
338 | //When a tag is present: Byte_i=[0-255]; Otherwise, when a tag is absent: [256].
339 | //================*/
340 |
341 | void serialEvent(Serial port) {
342 | String inData = port.readStringUntil('\n'); // read the serial string until seeing a carriage return
343 | if (inData.charAt(0) >= 'A' && inData.charAt(0) <= 'D') {
344 | int i = inData.charAt(0)-'A';
345 | int v = int(trim(inData.substring(1)));
346 | nfcs.rfid[i] = (v>255?-1:v);
347 | if (i==3) nfcs.checkTagID(); // process the tag ID when a sequence is collected completely.
348 | }
349 | return;
350 | }
351 |
352 | //print the current tag read by the reader
353 | void printCurrentTag() {
354 | if (nfcs.rfid[0]<0) println("No tag");
355 | else println(nfcs.rfid[0], ",", nfcs.rfid[1], ",", nfcs.rfid[2], ",", nfcs.rfid[3]);
356 | }
357 |
--------------------------------------------------------------------------------
/examples/episode2/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/.DS_Store
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagAlpha/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagAlpha/.DS_Store
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagAlpha/data/tagProfile.csv:
--------------------------------------------------------------------------------
1 | UID0,UID1,UID2,UID3,Label,Ttype,Mtype,L1,L2
2 | 136,4,87,200,A,2,1,0.0,0.0
3 | 136,4,72,200,B,2,1,0.0,0.0
4 | 136,4,232,199,C,2,1,0.0,0.0
5 | 136,4,237,199,D,2,1,0.0,0.0
6 | 136,4,21,199,E,2,1,0.0,0.0
7 | 136,4,53,200,F,2,1,0.0,0.0
8 | 136,4,1,199,G,2,1,0.0,0.0
9 | 136,4,58,200,H,2,1,0.0,0.0
10 | 136,4,52,200,I,2,1,0.0,0.0
11 | 136,4,68,200,J,2,1,0.0,0.0
12 | 136,4,16,199,K,2,1,0.0,0.0
13 | 136,4,47,200,L,2,1,0.0,0.0
14 | 136,4,222,199,M,2,1,0.0,0.0
15 | 136,4,242,199,N,2,1,0.0,0.0
16 | 136,4,63,200,O,2,1,0.0,0.0
17 | 136,4,252,199,P,2,1,0.0,0.0
18 | 136,4,77,200,Q,2,1,0.0,0.0
19 | 136,4,227,199,R,2,1,0.0,0.0
20 | 136,4,92,200,S,2,1,0.0,0.0
21 | 136,4,48,200,T,2,1,0.0,0.0
22 | 136,4,247,199,U,2,1,0.0,0.0
23 | 136,4,27,200,V,2,1,0.0,0.0
24 | 136,4,82,200,W,2,1,0.0,0.0
25 | 136,4,31,199,X,2,1,0.0,0.0
26 | 136,4,37,200,Y,2,1,0.0,0.0
27 | 136,4,26,199,Z,2,1,0.0,0.0
28 | 136,4,129,200,0,2,1,0.0,0.0
29 | 136,4,32,200,1,2,1,0.0,0.0
30 | 136,4,126,199,2,2,1,0.0,0.0
31 | 136,4,111,199,3,2,1,0.0,0.0
32 | 136,4,121,199,4,2,1,0.0,0.0
33 | 136,4,116,199,5,2,1,0.0,0.0
34 | 136,4,101,199,6,2,1,0.0,0.0
35 | 136,4,91,199,7,2,1,0.0,0.0
36 | 136,4,96,199,8,2,1,0.0,0.0
37 | 136,4,106,199,9,2,1,0.0,0.0
38 | 136,4,107,200,Apple,2,1,0.0,0.0
39 | 136,4,112,200,2,2,1,0.0,0.0
40 | 136,4,117,200,Carrot,2,1,0.0,0.0
41 | 136,4,22,200,1,2,1,0.0,0.0
42 | 136,4,36,199,3,2,1,0.0,0.0
43 | 136,4,102,200,Banana,2,1,0.0,0.0
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagAlpha/e1_SingleTagAlpha.pde:
--------------------------------------------------------------------------------
1 | /*==========================================================================
2 | // OpenNFCSense4P (v2) - Open NFCSense API for Processing Language
3 | // Copyright (C) 2021 Dr. Rong-Hao Liang
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //==========================================================================*/
17 | // e1_SingleTagRotation.pde:
18 | // This software works with a microcontroller running Arduino code and connected to an RC522 NFC/RFID Reader
19 | // OpenNFCSense API Github repository: https://github.com/howieliang/OpenNFCSense
20 | // NFCSense Project website: https://ronghaoliang.page/NFCSense/
21 |
22 | import processing.serial.*;
23 | import OpenNFCSense4P.*;
24 | Serial port;
25 | OpenNFCSense4P nfcs;
26 |
27 | String lastString = "";
28 | String tempString = "";
29 | long timer = 0;
30 | boolean bEntered = true;
31 |
32 | void setup() {
33 | size(800, 600, P2D); //Start a 800x600 px canvas (using P2D renderer)
34 | //nfcs = new OpenNFCSense4P(this, "tagProfile.csv"); //Initialize OpenNFCSense with the tag profiles (*.csv) in /data
35 | nfcs = new OpenNFCSense4P(this, "tagProfile.csv", 300, 300, 300);
36 | ////set frame rate to 250fps, TTL timer1 to 500ms, and TTL timer2 to 2000ms
37 | initSerial(); //Initialize the serial port
38 | /*== Put your codes below ==*/
39 | /*== Put your codes above ==*/
40 | }
41 |
42 | void draw() {
43 | nfcs.updateNFCBits(); //update the features of current bit
44 | /*== Put your codes below ==*/
45 | ArrayList nbitList = nfcs.getNFCBits();
46 | if (nbitList.size()>0) {
47 | lastString = "";
48 | tempString = "";
49 | for (int i = nbitList.size()-1; i >=0; i--) {
50 | NFCBit nb = nbitList.get(i);
51 | tempString += nb.getName();
52 | }
53 | timer = millis();
54 | bEntered = false;
55 | }
56 | /*== Put your codes above ==*/
57 | background(255); //Refresh the screen
58 | nfcs.drawMotionModeRecords(50, 2*height/3, 2*width/3, height/3-50); //draw the motion mode record of last second (x,y,width,height)
59 | /*== Put your codes below ==*/
60 | if (millis()-timer>100 && bEntered == false) {
61 | lastString = tempString;
62 | bEntered = true;
63 | }
64 | if (millis()-timer>2000){
65 | lastString = "";
66 | }
67 | drawString(lastString,50,100);
68 | /*== Put your codes above ==*/
69 | drawRecentBits(50, height/4+100); //draw the basic information of the recent NFCBits (within Timer2)
70 | drawInfo(width, height); //draw the version, read rate, and TTL timer info
71 | //printLastBit(); //print the extra information of the last NFCBit in the console
72 | //printCurrentTag(); //print the current tag read by the reader
73 | }
74 |
75 | /*Initialize the serial port*/
76 | void initSerial() {
77 | for (int i = 0; i < Serial.list().length; i++) println("[", i, "]:", Serial.list()[i]); //print the serial port
78 | port = new Serial(this, Serial.list()[Serial.list().length-1], 115200); //for Mac and Linux
79 | // port = new Serial(this, Serial.list()[0], 115200); // for PC
80 | port.bufferUntil('\n'); // arduino ends each data packet with a carriage return
81 | port.clear(); // flush the Serial buffer
82 | }
83 |
84 | /*draw a formatted String*/
85 | void drawString(String s, int x, int y) { //print the latest tag appearance
86 | pushStyle();
87 | fill(0);
88 | textSize(48);
89 | text(s, x, y);
90 | popStyle();
91 | }
92 |
93 | void drawSpeedmeter(float TacoValue, float _x, float _y, float _w, float _h, float _r) {
94 | float blight = 90;
95 | float r = _r;
96 | pushStyle();
97 | colorMode(HSB, 140);
98 | float TacoValueMap = map(TacoValue, 0, 30, -40, 220);
99 | float theta = radians(TacoValueMap);
100 | float x;
101 | float y;
102 | x = -r*cos(theta);
103 | y = -r*sin(theta);
104 |
105 | fill(30, 0, blight);
106 | textAlign(CENTER);
107 | textSize(50);
108 |
109 | pushMatrix();
110 | translate(_x, _y);
111 |
112 | pushMatrix();
113 | translate(_w/2, _h/2);
114 | rotate(-70 * PI / 180);
115 | strokeCap(SQUARE);
116 | strokeWeight(10);
117 | stroke(55, 99, 30);
118 | for (int i = 0; i < 7; i++) {
119 | rotate(40 * PI / 180);
120 | line(-r-10, 0, -r+33, 0);
121 | }
122 | popMatrix();
123 |
124 | pushMatrix();
125 | translate(_w/2, _h/2);
126 | rotate(-70 * PI / 180);
127 | strokeCap(ROUND);
128 | strokeWeight(8);
129 | stroke(55, 80, blight);
130 | for (int i = 0; i < 7; i++) {
131 | rotate(40 * PI / 180);
132 | line(-r-8, 0, -r+32, 0);
133 | }
134 | popMatrix();
135 |
136 | pushMatrix();
137 | translate(_w/2, _h/2);
138 | rotate(-30 * PI / 180);
139 | strokeCap(ROUND);
140 | strokeWeight(4);
141 | stroke(55, 80, blight);
142 | for (int i = 0; i < 24; i++) {
143 | rotate(10 * PI / 180);
144 | line(-r-8, 0, -r+10, 0);
145 | }
146 | popMatrix();
147 |
148 | pushMatrix();
149 | translate(_w/2, _h/2);
150 | rotate(-30 * PI / 180);
151 | strokeCap(ROUND);
152 | strokeWeight(4);
153 | stroke(55, 80, blight);
154 | for (int i = 0; i < 48; i++) {
155 | rotate(5 * PI / 180);
156 | line(-r-8, 0, -r, 0);
157 | }
158 | popMatrix();
159 |
160 | pushMatrix();
161 | translate(_w/2, _h/2);
162 | noFill();
163 | stroke(0, 0, 50);
164 | strokeWeight(15);
165 | stroke(0, 99, 30);
166 | strokeWeight(12);
167 | strokeCap(ROUND);
168 | line(0, 0, x, y);
169 | stroke(0, 99, blight);
170 | strokeWeight(8);
171 | line(0, 0, x, y);
172 | stroke(0, 0, blight);
173 | strokeWeight(6);
174 | line(x/10, y/10, x/5, y/5);
175 | popMatrix();
176 |
177 | stroke(0, 0, 30);
178 | strokeWeight(3);
179 | fill(0, 0, blight);
180 | ellipse(_w/2, _h/2, 44, 44);
181 | popMatrix();
182 | popStyle();
183 | println(TacoValueMap);
184 | }
185 |
186 | /*draw the basic information of the last NFCBit*/
187 | void drawLastBit(int x, int y) { //print the latest tag appearance
188 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
189 | String objInfo = "Current object: ", motionInfo = "";
190 | String tagID = "";
191 | if (nbitList.size()>0) {
192 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
193 | tagID = "["+nfcs.getIDTable().get(0)+"]"; // get the ID string of the latest tag
194 | objInfo += nb.getName();
195 | if (nb.getMode()!=NFCBit.NA) { // if the feature is ready (mode!=NA=0)
196 | if (nb.isFrequency()) { // if the NFCBit is a frequency bit
197 | motionInfo += nb.getModeString()+" at "+nf(nb.getFrequency(), 0, 2)+" Hz"; //show the motion mode and the motion frequency
198 | } else {
199 | motionInfo += nb.getModeString()+" at "+nf(nb.getSpeed(), 0, 2)+" km/h"; //show the motion mode and the motion speed
200 | }
201 | }
202 | }
203 | pushStyle();
204 | fill(0);
205 | textSize(48);
206 | text(objInfo, x, y);
207 | textSize(32);
208 | text(motionInfo, x, y+48);
209 | textSize(16);
210 | text(tagID, x, y+48+32);
211 | popStyle();
212 | }
213 |
214 | /*draw the basic information of the recent NFCBits (within timer 2)*/
215 | void drawRecentBits(int x, int y) {
216 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
217 | ArrayList IDList = nfcs.getIDTable(); // get the ID string of the recent NFCBits
218 | String tagName = "";
219 | String tagID = "";
220 | //for (int i = 0; i < nbitList.size(); i++) { // to reverse the order
221 | for (int i = nbitList.size()-1; i >=0; i--) {
222 | NFCBit nb = nbitList.get(i);
223 | tagName += nb.getName();
224 | tagID += "["+IDList.get(i)+"]";
225 | if (i>0) {
226 | tagName += ", ";
227 | tagID += ", ";
228 | }
229 | }
230 | pushStyle();
231 | fill(0);
232 | textSize(48);
233 | text("Recent objects: ", x, y);
234 | textSize(32);
235 | text(tagName, x, y+48);
236 | textSize(16);
237 | text(tagID, x, y+48+32);
238 | popStyle();
239 | }
240 |
241 | /*draw the version, read rate, and TTL timer info*/
242 | void drawInfo(int x, int y) {
243 | String info = "[Open NFCSense] ver. "+OpenNFCSense4P.version()+"\n"; //get the current library version
244 | info += "Read rate: "+nf(nfcs.getReadRate(), 0, 0)+" reads/sec\n"; // get the current read rate
245 | info += "TTL Timer1: "+nf(nfcs.getTimer1(), 0, 0)+" ms\n"; // get the current TTL timer1
246 | info += "TTL Timer2: "+nf(nfcs.getTimer2(), 0, 0)+" ms"; // get the current TTL timer2
247 | //set the above parameters in the constructor as indicated in setup();
248 | pushStyle();
249 | fill(100);
250 | textSize(12);
251 | textAlign(RIGHT, BOTTOM);
252 | text(info, x-5, y-5);
253 | popStyle();
254 | }
255 |
256 | /*print the extra information of the recent NFCBits in the console*/
257 | void printRecentBits() {
258 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
259 | for (int i = 0; i < nbitList.size(); i++) {
260 | NFCBit nb = nbitList.get(i); // get the latest NFCBit at index i
261 | String tagID = "["+nfcs.getIDTable().get(i)+"]"; //get the ID string of the latest tag
262 | print("[", i, "]", tagID, nb.getName(), ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
263 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
264 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
265 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
266 | //the type of motion (e.g., linear translation, rotation, shm, compound+motion)
267 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
268 | //the features (speed and frequency)
269 | }
270 | println("===");
271 | }
272 |
273 | /*print the extra information of the last NFCBit in the console*/
274 | void printLastBit() {
275 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
276 | if (nbitList.size()>0) {
277 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
278 | String tagID = "["+nfcs.getIDTable().get(0)+"]"; //get the ID string of the latest tag
279 | print(nb.getName(), tagID, ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
280 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
281 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
282 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
283 | //the type of motion (e.g., linear translation, rotation, shm, compound, compound+motion)
284 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
285 | //the features (speed and frequency)
286 | }
287 | println("===");
288 | }
289 |
290 | /*The serial event handler processes the data from any NFC reader in the String format of
291 | // "A[Byte_0]\n, B[Byte_1]\n, C[Byte_2]\n, or D[Byte_3]\n",
292 | //where every byte is an unsigned integer ranged between [0-256].
293 | //When a tag is present: Byte_i=[0-255]; Otherwise, when a tag is absent: [256].
294 | //================*/
295 |
296 | void serialEvent(Serial port) {
297 | String inData = port.readStringUntil('\n'); // read the serial string until seeing a carriage return
298 | if (inData.charAt(0) >= 'A' && inData.charAt(0) <= 'D') {
299 | int i = inData.charAt(0)-'A';
300 | int v = int(trim(inData.substring(1)));
301 | nfcs.rfid[i] = (v>255?-1:v);
302 | if (i==3) nfcs.checkTagID(); // process the tag ID when a sequence is collected completely.
303 | }
304 | return;
305 | }
306 |
307 | //print the current tag read by the reader
308 | void printCurrentTag() {
309 | if (nfcs.rfid[0]<0) println("No tag");
310 | else println(nfcs.rfid[0], ",", nfcs.rfid[1], ",", nfcs.rfid[2], ",", nfcs.rfid[3]);
311 | }
312 |
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagLoops/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagLoops/.DS_Store
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagLoops/data/apple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagLoops/data/apple.png
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagLoops/data/banana.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagLoops/data/banana.png
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagLoops/data/carrot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagLoops/data/carrot.png
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagLoops/data/tagProfile.csv:
--------------------------------------------------------------------------------
1 | UID0,UID1,UID2,UID3,Label,Ttype,Mtype,L1,L2
2 | 136,4,87,200,A,2,1,0.0,0.0
3 | 136,4,72,200,B,2,1,0.0,0.0
4 | 136,4,232,199,C,2,1,0.0,0.0
5 | 136,4,237,199,D,2,1,0.0,0.0
6 | 136,4,21,199,E,2,1,0.0,0.0
7 | 136,4,53,200,F,2,1,0.0,0.0
8 | 136,4,1,199,G,2,1,0.0,0.0
9 | 136,4,58,200,H,2,1,0.0,0.0
10 | 136,4,52,200,I,2,1,0.0,0.0
11 | 136,4,68,200,J,2,1,0.0,0.0
12 | 136,4,16,199,K,2,1,0.0,0.0
13 | 136,4,47,200,L,2,1,0.0,0.0
14 | 136,4,222,199,M,2,1,0.0,0.0
15 | 136,4,242,199,N,2,1,0.0,0.0
16 | 136,4,63,200,O,2,1,0.0,0.0
17 | 136,4,252,199,P,2,1,0.0,0.0
18 | 136,4,77,200,Q,2,1,0.0,0.0
19 | 136,4,227,199,R,2,1,0.0,0.0
20 | 136,4,92,200,S,2,1,0.0,0.0
21 | 136,4,48,200,T,2,1,0.0,0.0
22 | 136,4,247,199,U,2,1,0.0,0.0
23 | 136,4,27,200,V,2,1,0.0,0.0
24 | 136,4,82,200,W,2,1,0.0,0.0
25 | 136,4,31,199,X,2,1,0.0,0.0
26 | 136,4,37,200,Y,2,1,0.0,0.0
27 | 136,4,26,199,Z,2,1,0.0,0.0
28 | 136,4,129,200,0,2,1,0.0,0.0
29 | 136,4,32,200,1,2,1,0.0,0.0
30 | 136,4,126,199,2,2,1,0.0,0.0
31 | 136,4,111,199,3,2,1,0.0,0.0
32 | 136,4,121,199,4,2,1,0.0,0.0
33 | 136,4,116,199,5,2,1,0.0,0.0
34 | 136,4,101,199,6,2,1,0.0,0.0
35 | 136,4,91,199,7,2,1,0.0,0.0
36 | 136,4,96,199,8,2,1,0.0,0.0
37 | 136,4,106,199,9,2,1,0.0,0.0
38 | 136,4,107,200,Apple,2,1,0.0,0.0
39 | 136,4,112,200,2,2,1,0.0,0.0
40 | 136,4,117,200,Carrot,2,1,0.0,0.0
41 | 136,4,22,200,1,2,1,0.0,0.0
42 | 136,4,36,199,3,2,1,0.0,0.0
43 | 136,4,102,200,Banana,2,1,0.0,0.0
44 | 136,4,121,150,power2,2,1,0.0,0.0
45 | 136,4,130,150,power3,2,1,0.0,0.0
46 | 136,4,129,150,for,2,1,0.0,0.0
47 | 136,4,146,150,while,2,1,0.0,0.0
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagLoops/e1_SingleTagLoops.pde:
--------------------------------------------------------------------------------
1 | /*==========================================================================
2 | // OpenNFCSense4P (v2) - Open NFCSense API for Processing Language
3 | // Copyright (C) 2021 Dr. Rong-Hao Liang
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //==========================================================================*/
17 | // e1_SingleTagRotation.pde:
18 | // This software works with a microcontroller running Arduino code and connected to an RC522 NFC/RFID Reader
19 | // OpenNFCSense API Github repository: https://github.com/howieliang/OpenNFCSense
20 | // NFCSense Project website: https://ronghaoliang.page/NFCSense/
21 |
22 | import processing.serial.*;
23 | import OpenNFCSense4P.*;
24 | Serial port;
25 | OpenNFCSense4P nfcs;
26 |
27 | String lastString = "";
28 | String tempString = "";
29 | long timer = 0;
30 | boolean bEntered = true;
31 |
32 | String[] QStrings = {"16 = ", "9 = ", "27 = "};
33 | String[] AStrings = {"4C", "3C", "3D"};
34 | int qIndex = 0;
35 | boolean bCorrect = false;
36 |
37 | PImage[] img = new PImage[3];
38 | int pw;
39 |
40 | void setup() {
41 | size(800, 600, P2D); //Start a 800x600 px canvas (using P2D renderer)
42 | //nfcs = new OpenNFCSense4P(this, "tagProfile.csv"); //Initialize OpenNFCSense with the tag profiles (*.csv) in /data
43 | nfcs = new OpenNFCSense4P(this, "tagProfile.csv", 300, 300, 300);
44 | ////set frame rate to 250fps, TTL timer1 to 500ms, and TTL timer2 to 2000ms
45 | initSerial(); //Initialize the serial port
46 | /*== Put your codes below ==*/
47 | /*== Put your codes above ==*/
48 | }
49 |
50 | void draw() {
51 | nfcs.updateNFCBits(); //update the features of current bit
52 | /*== Put your codes below ==*/
53 | ArrayList nbitList = nfcs.getNFCBits();
54 | if (nbitList.size()>0) {
55 | lastString = "";
56 | tempString = "";
57 | for (int i = nbitList.size()-1; i >=0; i--) {
58 | NFCBit nb = nbitList.get(i);
59 | if (nb.getName().equals("for")) tempString += "A";
60 | else if (nb.getName().equals("while")) tempString += "B";
61 | else tempString += nb.getName();
62 | }
63 | timer = millis();
64 | bEntered = false;
65 | }
66 | /*== Put your codes above ==*/
67 | background(255); //Refresh the screen
68 | nfcs.drawMotionModeRecords(50, 2*height/3, 2*width/3, height/3-50); //draw the motion mode record of last second (x,y,width,height)
69 | /*== Put your codes below ==*/
70 | if (millis()-timer>100 && bEntered == false) {
71 | lastString = tempString;
72 | bEntered = true;
73 | }
74 | if (millis()-timer>5000) {
75 | lastString = "";
76 | }
77 | if (lastString.equals("")) {
78 | drawString("Output:", 50, 50, color(0),48);
79 | drawString("0", 50, 100, color(0),48);
80 | drawString("Code:", 450, 50, color(0),48);
81 | drawString("int i=0", 450, 100+0*24, color(0),24);
82 | drawString("{", 450, 100+1*24, color(0),24);
83 | drawString(" print(i+\',\');", 450, 100+2*24, color(0),24);
84 | drawString("}", 450, 100+3*24, color(0),24);
85 | } else {
86 | if (lastString.charAt(0)=='A') {
87 | if (lastString.length()>=2) {
88 | int n1 = lastString.charAt(1)-'0';
89 | int n2 = lastString.charAt(2)-'0';
90 | int n3 = lastString.charAt(3)-'0';
91 | String s = "";
92 | int i = 0;
93 | for (i=n1; i=2) {
108 | int n1 = lastString.charAt(1)-'0';
109 | String s = "";
110 | int i = 0;
111 | while (i< n1){
112 | s += i;
113 | s += ",";
114 | i += 1;
115 | }
116 | drawString("Output:", 50, 50, color(0),48);
117 | drawString(s, 50, 100, color(22, 160, 133),48);
118 | drawString("Code:", 450, 50, color(0),48);
119 | drawString("int i=0;", 450, 100+0*24, color(0),24);
120 | drawString("while (i<"+n1+") {", 450, 100+1*24, color(22, 160, 133),24);
121 | drawString(" print(i+\',\');", 450, 100+2*24, color(0),24);
122 | drawString(" i = i+1;", 450, 100+3*24, color(22, 160, 133),24);
123 | drawString("}", 450, 100+4*24, color(22, 160, 133),24);
124 | }
125 | }
126 | }
127 | /*== Put your codes above ==*/
128 | drawRecentBits(50, height/4+100); //draw the basic information of the recent NFCBits (within Timer2)
129 | drawInfo(width, height); //draw the version, read rate, and TTL timer info
130 | //printLastBit(); //print the extra information of the last NFCBit in the console
131 | printCurrentTag(); //print the current tag read by the reader
132 | }
133 |
134 | /*Initialize the serial port*/
135 | void initSerial() {
136 | for (int i = 0; i < Serial.list().length; i++) println("[", i, "]:", Serial.list()[i]); //print the serial port
137 | port = new Serial(this, Serial.list()[Serial.list().length-1], 115200); //for Mac and Linux
138 | // port = new Serial(this, Serial.list()[0], 115200); // for PC
139 | port.bufferUntil('\n'); // arduino ends each data packet with a carriage return
140 | port.clear(); // flush the Serial buffer
141 | }
142 |
143 | /*draw a formatted String*/
144 | void drawString(String s, int x, int y, color c, float t) { //print the latest tag appearance
145 | pushStyle();
146 | textAlign(LEFT, TOP);
147 | fill(c);
148 | textSize(t);
149 | text(s, x, y);
150 | popStyle();
151 | }
152 |
153 | void drawSpeedmeter(float TacoValue, float _x, float _y, float _w, float _h, float _r) {
154 | float blight = 90;
155 | float r = _r;
156 | pushStyle();
157 | colorMode(HSB, 140);
158 | float TacoValueMap = map(TacoValue, 0, 30, -40, 220);
159 | float theta = radians(TacoValueMap);
160 | float x;
161 | float y;
162 | x = -r*cos(theta);
163 | y = -r*sin(theta);
164 |
165 | fill(30, 0, blight);
166 | textAlign(CENTER);
167 | textSize(50);
168 |
169 | pushMatrix();
170 | translate(_x, _y);
171 |
172 | pushMatrix();
173 | translate(_w/2, _h/2);
174 | rotate(-70 * PI / 180);
175 | strokeCap(SQUARE);
176 | strokeWeight(10);
177 | stroke(55, 99, 30);
178 | for (int i = 0; i < 7; i++) {
179 | rotate(40 * PI / 180);
180 | line(-r-10, 0, -r+33, 0);
181 | }
182 | popMatrix();
183 |
184 | pushMatrix();
185 | translate(_w/2, _h/2);
186 | rotate(-70 * PI / 180);
187 | strokeCap(ROUND);
188 | strokeWeight(8);
189 | stroke(55, 80, blight);
190 | for (int i = 0; i < 7; i++) {
191 | rotate(40 * PI / 180);
192 | line(-r-8, 0, -r+32, 0);
193 | }
194 | popMatrix();
195 |
196 | pushMatrix();
197 | translate(_w/2, _h/2);
198 | rotate(-30 * PI / 180);
199 | strokeCap(ROUND);
200 | strokeWeight(4);
201 | stroke(55, 80, blight);
202 | for (int i = 0; i < 24; i++) {
203 | rotate(10 * PI / 180);
204 | line(-r-8, 0, -r+10, 0);
205 | }
206 | popMatrix();
207 |
208 | pushMatrix();
209 | translate(_w/2, _h/2);
210 | rotate(-30 * PI / 180);
211 | strokeCap(ROUND);
212 | strokeWeight(4);
213 | stroke(55, 80, blight);
214 | for (int i = 0; i < 48; i++) {
215 | rotate(5 * PI / 180);
216 | line(-r-8, 0, -r, 0);
217 | }
218 | popMatrix();
219 |
220 | pushMatrix();
221 | translate(_w/2, _h/2);
222 | noFill();
223 | stroke(0, 0, 50);
224 | strokeWeight(15);
225 | stroke(0, 99, 30);
226 | strokeWeight(12);
227 | strokeCap(ROUND);
228 | line(0, 0, x, y);
229 | stroke(0, 99, blight);
230 | strokeWeight(8);
231 | line(0, 0, x, y);
232 | stroke(0, 0, blight);
233 | strokeWeight(6);
234 | line(x/10, y/10, x/5, y/5);
235 | popMatrix();
236 |
237 | stroke(0, 0, 30);
238 | strokeWeight(3);
239 | fill(0, 0, blight);
240 | ellipse(_w/2, _h/2, 44, 44);
241 | popMatrix();
242 | popStyle();
243 | println(TacoValueMap);
244 | }
245 |
246 | /*draw the basic information of the last NFCBit*/
247 | void drawLastBit(int x, int y) { //print the latest tag appearance
248 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
249 | String objInfo = "Current object: ", motionInfo = "";
250 | String tagID = "";
251 | if (nbitList.size()>0) {
252 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
253 | tagID = "["+nfcs.getIDTable().get(0)+"]"; // get the ID string of the latest tag
254 | objInfo += nb.getName();
255 | if (nb.getMode()!=NFCBit.NA) { // if the feature is ready (mode!=NA=0)
256 | if (nb.isFrequency()) { // if the NFCBit is a frequency bit
257 | motionInfo += nb.getModeString()+" at "+nf(nb.getFrequency(), 0, 2)+" Hz"; //show the motion mode and the motion frequency
258 | } else {
259 | motionInfo += nb.getModeString()+" at "+nf(nb.getSpeed(), 0, 2)+" km/h"; //show the motion mode and the motion speed
260 | }
261 | }
262 | }
263 | pushStyle();
264 | fill(0);
265 | textSize(48);
266 | text(objInfo, x, y);
267 | textSize(32);
268 | text(motionInfo, x, y+48);
269 | textSize(16);
270 | text(tagID, x, y+48+32);
271 | popStyle();
272 | }
273 |
274 | /*draw the basic information of the recent NFCBits (within timer 2)*/
275 | void drawRecentBits(int x, int y) {
276 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
277 | ArrayList IDList = nfcs.getIDTable(); // get the ID string of the recent NFCBits
278 | String tagName = "";
279 | String tagID = "";
280 | //for (int i = 0; i < nbitList.size(); i++) { // to reverse the order
281 | for (int i = nbitList.size()-1; i >=0; i--) {
282 | NFCBit nb = nbitList.get(i);
283 | tagName += nb.getName();
284 | tagID += "["+IDList.get(i)+"]";
285 | if (i>0) {
286 | tagName += ", ";
287 | tagID += ", ";
288 | }
289 | }
290 | pushStyle();
291 | fill(0);
292 | textSize(48);
293 | text("Recent objects: ", x, y);
294 | textSize(32);
295 | text(tagName, x, y+48);
296 | textSize(16);
297 | text(tagID, x, y+48+32);
298 | popStyle();
299 | }
300 |
301 | /*draw the version, read rate, and TTL timer info*/
302 | void drawInfo(int x, int y) {
303 | String info = "[Open NFCSense] ver. "+OpenNFCSense4P.version()+"\n"; //get the current library version
304 | info += "Read rate: "+nf(nfcs.getReadRate(), 0, 0)+" reads/sec\n"; // get the current read rate
305 | info += "TTL Timer1: "+nf(nfcs.getTimer1(), 0, 0)+" ms\n"; // get the current TTL timer1
306 | info += "TTL Timer2: "+nf(nfcs.getTimer2(), 0, 0)+" ms"; // get the current TTL timer2
307 | //set the above parameters in the constructor as indicated in setup();
308 | pushStyle();
309 | fill(100);
310 | textSize(12);
311 | textAlign(RIGHT, BOTTOM);
312 | text(info, x-5, y-5);
313 | popStyle();
314 | }
315 |
316 | /*print the extra information of the recent NFCBits in the console*/
317 | void printRecentBits() {
318 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
319 | for (int i = 0; i < nbitList.size(); i++) {
320 | NFCBit nb = nbitList.get(i); // get the latest NFCBit at index i
321 | String tagID = "["+nfcs.getIDTable().get(i)+"]"; //get the ID string of the latest tag
322 | print("[", i, "]", tagID, nb.getName(), ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
323 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
324 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
325 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
326 | //the type of motion (e.g., linear translation, rotation, shm, compound+motion)
327 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
328 | //the features (speed and frequency)
329 | }
330 | println("===");
331 | }
332 |
333 | /*print the extra information of the last NFCBit in the console*/
334 | void printLastBit() {
335 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
336 | if (nbitList.size()>0) {
337 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
338 | String tagID = "["+nfcs.getIDTable().get(0)+"]"; //get the ID string of the latest tag
339 | print(nb.getName(), tagID, ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
340 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
341 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
342 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
343 | //the type of motion (e.g., linear translation, rotation, shm, compound, compound+motion)
344 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
345 | //the features (speed and frequency)
346 | }
347 | println("===");
348 | }
349 |
350 | /*The serial event handler processes the data from any NFC reader in the String format of
351 | // "A[Byte_0]\n, B[Byte_1]\n, C[Byte_2]\n, or D[Byte_3]\n",
352 | //where every byte is an unsigned integer ranged between [0-256].
353 | //When a tag is present: Byte_i=[0-255]; Otherwise, when a tag is absent: [256].
354 | //================*/
355 |
356 | void serialEvent(Serial port) {
357 | String inData = port.readStringUntil('\n'); // read the serial string until seeing a carriage return
358 | if (inData.charAt(0) >= 'A' && inData.charAt(0) <= 'D') {
359 | int i = inData.charAt(0)-'A';
360 | int v = int(trim(inData.substring(1)));
361 | nfcs.rfid[i] = (v>255?-1:v);
362 | if (i==3) nfcs.checkTagID(); // process the tag ID when a sequence is collected completely.
363 | }
364 | return;
365 | }
366 |
367 | //print the current tag read by the reader
368 | void printCurrentTag() {
369 | if (nfcs.rfid[0]<0) println("No tag");
370 | else println(nfcs.rfid[0], ",", nfcs.rfid[1], ",", nfcs.rfid[2], ",", nfcs.rfid[3]);
371 | }
372 |
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagNumSym/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagNumSym/.DS_Store
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagNumSym/data/apple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagNumSym/data/apple.png
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagNumSym/data/banana.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagNumSym/data/banana.png
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagNumSym/data/carrot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagNumSym/data/carrot.png
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagNumSym/data/tagProfile.csv:
--------------------------------------------------------------------------------
1 | UID0,UID1,UID2,UID3,Label,Ttype,Mtype,L1,L2
2 | 136,4,87,200,A,2,1,0.0,0.0
3 | 136,4,72,200,B,2,1,0.0,0.0
4 | 136,4,232,199,C,2,1,0.0,0.0
5 | 136,4,237,199,D,2,1,0.0,0.0
6 | 136,4,21,199,E,2,1,0.0,0.0
7 | 136,4,53,200,F,2,1,0.0,0.0
8 | 136,4,1,199,G,2,1,0.0,0.0
9 | 136,4,58,200,H,2,1,0.0,0.0
10 | 136,4,52,200,I,2,1,0.0,0.0
11 | 136,4,68,200,J,2,1,0.0,0.0
12 | 136,4,16,199,K,2,1,0.0,0.0
13 | 136,4,47,200,L,2,1,0.0,0.0
14 | 136,4,222,199,M,2,1,0.0,0.0
15 | 136,4,242,199,N,2,1,0.0,0.0
16 | 136,4,63,200,O,2,1,0.0,0.0
17 | 136,4,252,199,P,2,1,0.0,0.0
18 | 136,4,77,200,Q,2,1,0.0,0.0
19 | 136,4,227,199,R,2,1,0.0,0.0
20 | 136,4,92,200,S,2,1,0.0,0.0
21 | 136,4,48,200,T,2,1,0.0,0.0
22 | 136,4,247,199,U,2,1,0.0,0.0
23 | 136,4,27,200,V,2,1,0.0,0.0
24 | 136,4,82,200,W,2,1,0.0,0.0
25 | 136,4,31,199,X,2,1,0.0,0.0
26 | 136,4,37,200,Y,2,1,0.0,0.0
27 | 136,4,26,199,Z,2,1,0.0,0.0
28 | 136,4,129,200,0,2,1,0.0,0.0
29 | 136,4,32,200,1,2,1,0.0,0.0
30 | 136,4,126,199,2,2,1,0.0,0.0
31 | 136,4,111,199,3,2,1,0.0,0.0
32 | 136,4,121,199,4,2,1,0.0,0.0
33 | 136,4,116,199,5,2,1,0.0,0.0
34 | 136,4,101,199,6,2,1,0.0,0.0
35 | 136,4,91,199,7,2,1,0.0,0.0
36 | 136,4,96,199,8,2,1,0.0,0.0
37 | 136,4,106,199,9,2,1,0.0,0.0
38 | 136,4,107,200,Apple,2,1,0.0,0.0
39 | 136,4,112,200,2,2,1,0.0,0.0
40 | 136,4,117,200,Carrot,2,1,0.0,0.0
41 | 136,4,22,200,1,2,1,0.0,0.0
42 | 136,4,36,199,3,2,1,0.0,0.0
43 | 136,4,102,200,Banana,2,1,0.0,0.0
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagNumSym/e1_SingleTagNumSym.pde:
--------------------------------------------------------------------------------
1 | /*==========================================================================
2 | // OpenNFCSense4P (v2) - Open NFCSense API for Processing Language
3 | // Copyright (C) 2021 Dr. Rong-Hao Liang
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //==========================================================================*/
17 | // e1_SingleTagRotation.pde:
18 | // This software works with a microcontroller running Arduino code and connected to an RC522 NFC/RFID Reader
19 | // OpenNFCSense API Github repository: https://github.com/howieliang/OpenNFCSense
20 | // NFCSense Project website: https://ronghaoliang.page/NFCSense/
21 |
22 | import processing.serial.*;
23 | import OpenNFCSense4P.*;
24 | Serial port;
25 | OpenNFCSense4P nfcs;
26 |
27 | String lastString = "";
28 | String tempString = "";
29 | float lastFreq = 0;
30 | long timer = 0;
31 | boolean bEntered = true;
32 |
33 | String[] QStrings = {"1A2B", "2B3C", "3C1A"};
34 | String[] AStrings = {"1A2B", "2B3C", "3C1A"};
35 | int qIndex = 0;
36 | boolean bCorrect = false;
37 |
38 | PImage[] img = new PImage[3];
39 | int pw;
40 |
41 | void setup() {
42 | size(800, 600, P2D); //Start a 800x600 px canvas (using P2D renderer)
43 | //nfcs = new OpenNFCSense4P(this, "tagProfile.csv"); //Initialize OpenNFCSense with the tag profiles (*.csv) in /data
44 | nfcs = new OpenNFCSense4P(this, "tagProfile.csv", 300, 300, 300);
45 | ////set frame rate to 250fps, TTL timer1 to 500ms, and TTL timer2 to 2000ms
46 | initSerial(); //Initialize the serial port
47 | /*== Put your codes below ==*/
48 | img[0] = loadImage("apple.png");
49 | img[1] = loadImage("banana.png");
50 | img[2] = loadImage("carrot.png");
51 | pw = height/8;
52 | for (int i = 0; i < 3; i++) {
53 | img[i].resize(pw, pw);
54 | }
55 | /*== Put your codes above ==*/
56 | }
57 |
58 | void draw() {
59 | nfcs.updateNFCBits(); //update the features of current bit
60 | /*== Put your codes below ==*/
61 | ArrayList nbitList = nfcs.getNFCBits();
62 | if (nbitList.size()>0) {
63 | lastString = "";
64 | tempString = "";
65 | for (int i = nbitList.size()-1; i >=0; i--) {
66 | NFCBit nb = nbitList.get(i);
67 | if (nb.getName().equals("Apple")) tempString += "A";
68 | else if (nb.getName().equals("Banana")) tempString += "B";
69 | else if (nb.getName().equals("Carrot")) tempString += "C";
70 | else tempString += nb.getName();
71 | }
72 | timer = millis();
73 | bEntered = false;
74 | }
75 | /*== Put your codes above ==*/
76 | background(255); //Refresh the screen
77 | nfcs.drawMotionModeRecords(50, 2*height/3, 2*width/3, height/3-50); //draw the motion mode record of last second (x,y,width,height)
78 | /*== Put your codes below ==*/
79 | if (millis()-timer>100 && bEntered == false) {
80 | lastString = tempString;
81 | bEntered = true;
82 | }
83 | if (millis()-timer>2000) {
84 | if (!lastString.equals("")) {
85 | if (bCorrect) {
86 | ++qIndex;
87 | qIndex %= QStrings.length;
88 | lastString = "";
89 | } else {
90 | lastString = "";
91 | }
92 | }
93 | }
94 | if (lastString.equals("")) {
95 | drawString("Q:", 50, 40, color(0));
96 | drawString("A:", 50, 40+pw, color(0));
97 | } else {
98 | if (lastString.equals(AStrings[qIndex])) bCorrect = true;
99 | else bCorrect = false;
100 | drawString("Q:", 50, 40, color(0));
101 | if (bCorrect) drawString("A:", 50, 40+pw, color(22, 160, 133));
102 | else drawString("A:", 50, 40+pw, color(231, 76, 60));
103 | }
104 | int nq1 = (int)QStrings[qIndex].charAt(0)-'0';
105 | int oq1 = (int)QStrings[qIndex].charAt(1)-'A';
106 | int nq2 = (int)QStrings[qIndex].charAt(2)-'0';
107 | int oq2 = (int)QStrings[qIndex].charAt(3)-'A';
108 | for (int i = 0; i < nq1; i++) {
109 | image(img[oq1], 120+i*pw, 40);
110 | }
111 | for (int i = nq1; i < nq1+nq2; i++) {
112 | image(img[oq2], 120+i*pw, 40);
113 | }
114 | int n1 = 0;
115 | int o1 = 0;
116 | int n2 = 0;
117 | int o2 = 0;
118 | if(lastString.length()>=2){
119 | n1 = lastString.charAt(0)-'0';
120 | o1 = lastString.charAt(1)-'A';
121 | }
122 | if(lastString.length()>=4){
123 | n2 = lastString.charAt(2)-'0';
124 | o2 = lastString.charAt(3)-'A';
125 | }
126 | if (n1>0 && o1>=0) {
127 | for (int i = 0; i < n1; i++) {
128 | image(img[o1], 120+i*pw, 40+pw);
129 | }
130 | }
131 | if (n2>0 && o2>=0) {
132 | for (int i = n1; i < n1+n2; i++) {
133 | image(img[o2], 120+i*pw, 40+pw);
134 | }
135 | }
136 | /*== Put your codes above ==*/
137 | drawRecentBits(50, height/4+100); //draw the basic information of the recent NFCBits (within Timer2)
138 | drawInfo(width, height); //draw the version, read rate, and TTL timer info
139 | //printLastBit(); //print the extra information of the last NFCBit in the console
140 | //printCurrentTag(); //print the current tag read by the reader
141 | }
142 |
143 | /*Initialize the serial port*/
144 | void initSerial() {
145 | for (int i = 0; i < Serial.list().length; i++) println("[", i, "]:", Serial.list()[i]); //print the serial port
146 | port = new Serial(this, Serial.list()[Serial.list().length-1], 115200); //for Mac and Linux
147 | // port = new Serial(this, Serial.list()[0], 115200); // for PC
148 | port.bufferUntil('\n'); // arduino ends each data packet with a carriage return
149 | port.clear(); // flush the Serial buffer
150 | }
151 |
152 | /*draw a formatted String*/
153 | void drawString(String s, int x, int y, color c) { //print the latest tag appearance
154 | pushStyle();
155 | textAlign(LEFT,TOP);
156 | fill(c);
157 | textSize(48);
158 | text(s, x, y);
159 | popStyle();
160 | }
161 |
162 | void drawSpeedmeter(float TacoValue, float _x, float _y, float _w, float _h, float _r) {
163 | float blight = 90;
164 | float r = _r;
165 | pushStyle();
166 | colorMode(HSB, 140);
167 | float TacoValueMap = map(TacoValue, 0, 30, -40, 220);
168 | float theta = radians(TacoValueMap);
169 | float x;
170 | float y;
171 | x = -r*cos(theta);
172 | y = -r*sin(theta);
173 |
174 | fill(30, 0, blight);
175 | textAlign(CENTER);
176 | textSize(50);
177 |
178 | pushMatrix();
179 | translate(_x, _y);
180 |
181 | pushMatrix();
182 | translate(_w/2, _h/2);
183 | rotate(-70 * PI / 180);
184 | strokeCap(SQUARE);
185 | strokeWeight(10);
186 | stroke(55, 99, 30);
187 | for (int i = 0; i < 7; i++) {
188 | rotate(40 * PI / 180);
189 | line(-r-10, 0, -r+33, 0);
190 | }
191 | popMatrix();
192 |
193 | pushMatrix();
194 | translate(_w/2, _h/2);
195 | rotate(-70 * PI / 180);
196 | strokeCap(ROUND);
197 | strokeWeight(8);
198 | stroke(55, 80, blight);
199 | for (int i = 0; i < 7; i++) {
200 | rotate(40 * PI / 180);
201 | line(-r-8, 0, -r+32, 0);
202 | }
203 | popMatrix();
204 |
205 | pushMatrix();
206 | translate(_w/2, _h/2);
207 | rotate(-30 * PI / 180);
208 | strokeCap(ROUND);
209 | strokeWeight(4);
210 | stroke(55, 80, blight);
211 | for (int i = 0; i < 24; i++) {
212 | rotate(10 * PI / 180);
213 | line(-r-8, 0, -r+10, 0);
214 | }
215 | popMatrix();
216 |
217 | pushMatrix();
218 | translate(_w/2, _h/2);
219 | rotate(-30 * PI / 180);
220 | strokeCap(ROUND);
221 | strokeWeight(4);
222 | stroke(55, 80, blight);
223 | for (int i = 0; i < 48; i++) {
224 | rotate(5 * PI / 180);
225 | line(-r-8, 0, -r, 0);
226 | }
227 | popMatrix();
228 |
229 | pushMatrix();
230 | translate(_w/2, _h/2);
231 | noFill();
232 | stroke(0, 0, 50);
233 | strokeWeight(15);
234 | stroke(0, 99, 30);
235 | strokeWeight(12);
236 | strokeCap(ROUND);
237 | line(0, 0, x, y);
238 | stroke(0, 99, blight);
239 | strokeWeight(8);
240 | line(0, 0, x, y);
241 | stroke(0, 0, blight);
242 | strokeWeight(6);
243 | line(x/10, y/10, x/5, y/5);
244 | popMatrix();
245 |
246 | stroke(0, 0, 30);
247 | strokeWeight(3);
248 | fill(0, 0, blight);
249 | ellipse(_w/2, _h/2, 44, 44);
250 | popMatrix();
251 | popStyle();
252 | println(TacoValueMap);
253 | }
254 |
255 | /*draw the basic information of the last NFCBit*/
256 | void drawLastBit(int x, int y) { //print the latest tag appearance
257 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
258 | String objInfo = "Current object: ", motionInfo = "";
259 | String tagID = "";
260 | if (nbitList.size()>0) {
261 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
262 | tagID = "["+nfcs.getIDTable().get(0)+"]"; // get the ID string of the latest tag
263 | objInfo += nb.getName();
264 | if (nb.getMode()!=NFCBit.NA) { // if the feature is ready (mode!=NA=0)
265 | if (nb.isFrequency()) { // if the NFCBit is a frequency bit
266 | motionInfo += nb.getModeString()+" at "+nf(nb.getFrequency(), 0, 2)+" Hz"; //show the motion mode and the motion frequency
267 | } else {
268 | motionInfo += nb.getModeString()+" at "+nf(nb.getSpeed(), 0, 2)+" km/h"; //show the motion mode and the motion speed
269 | }
270 | }
271 | }
272 | pushStyle();
273 | fill(0);
274 | textSize(48);
275 | text(objInfo, x, y);
276 | textSize(32);
277 | text(motionInfo, x, y+48);
278 | textSize(16);
279 | text(tagID, x, y+48+32);
280 | popStyle();
281 | }
282 |
283 | /*draw the basic information of the recent NFCBits (within timer 2)*/
284 | void drawRecentBits(int x, int y) {
285 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
286 | ArrayList IDList = nfcs.getIDTable(); // get the ID string of the recent NFCBits
287 | String tagName = "";
288 | String tagID = "";
289 | //for (int i = 0; i < nbitList.size(); i++) { // to reverse the order
290 | for (int i = nbitList.size()-1; i >=0; i--) {
291 | NFCBit nb = nbitList.get(i);
292 | tagName += nb.getName();
293 | tagID += "["+IDList.get(i)+"]";
294 | if (i>0) {
295 | tagName += ", ";
296 | tagID += ", ";
297 | }
298 | }
299 | pushStyle();
300 | fill(0);
301 | textSize(48);
302 | text("Recent objects: ", x, y);
303 | textSize(32);
304 | text(tagName, x, y+48);
305 | textSize(16);
306 | text(tagID, x, y+48+32);
307 | popStyle();
308 | }
309 |
310 | /*draw the version, read rate, and TTL timer info*/
311 | void drawInfo(int x, int y) {
312 | String info = "[Open NFCSense] ver. "+OpenNFCSense4P.version()+"\n"; //get the current library version
313 | info += "Read rate: "+nf(nfcs.getReadRate(), 0, 0)+" reads/sec\n"; // get the current read rate
314 | info += "TTL Timer1: "+nf(nfcs.getTimer1(), 0, 0)+" ms\n"; // get the current TTL timer1
315 | info += "TTL Timer2: "+nf(nfcs.getTimer2(), 0, 0)+" ms"; // get the current TTL timer2
316 | //set the above parameters in the constructor as indicated in setup();
317 | pushStyle();
318 | fill(100);
319 | textSize(12);
320 | textAlign(RIGHT, BOTTOM);
321 | text(info, x-5, y-5);
322 | popStyle();
323 | }
324 |
325 | /*print the extra information of the recent NFCBits in the console*/
326 | void printRecentBits() {
327 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
328 | for (int i = 0; i < nbitList.size(); i++) {
329 | NFCBit nb = nbitList.get(i); // get the latest NFCBit at index i
330 | String tagID = "["+nfcs.getIDTable().get(i)+"]"; //get the ID string of the latest tag
331 | print("[", i, "]", tagID, nb.getName(), ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
332 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
333 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
334 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
335 | //the type of motion (e.g., linear translation, rotation, shm, compound+motion)
336 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
337 | //the features (speed and frequency)
338 | }
339 | println("===");
340 | }
341 |
342 | /*print the extra information of the last NFCBit in the console*/
343 | void printLastBit() {
344 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
345 | if (nbitList.size()>0) {
346 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
347 | String tagID = "["+nfcs.getIDTable().get(0)+"]"; //get the ID string of the latest tag
348 | print(nb.getName(), tagID, ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
349 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
350 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
351 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
352 | //the type of motion (e.g., linear translation, rotation, shm, compound, compound+motion)
353 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
354 | //the features (speed and frequency)
355 | }
356 | println("===");
357 | }
358 |
359 | /*The serial event handler processes the data from any NFC reader in the String format of
360 | // "A[Byte_0]\n, B[Byte_1]\n, C[Byte_2]\n, or D[Byte_3]\n",
361 | //where every byte is an unsigned integer ranged between [0-256].
362 | //When a tag is present: Byte_i=[0-255]; Otherwise, when a tag is absent: [256].
363 | //================*/
364 |
365 | void serialEvent(Serial port) {
366 | String inData = port.readStringUntil('\n'); // read the serial string until seeing a carriage return
367 | if (inData.charAt(0) >= 'A' && inData.charAt(0) <= 'D') {
368 | int i = inData.charAt(0)-'A';
369 | int v = int(trim(inData.substring(1)));
370 | nfcs.rfid[i] = (v>255?-1:v);
371 | if (i==3) nfcs.checkTagID(); // process the tag ID when a sequence is collected completely.
372 | }
373 | return;
374 | }
375 |
376 | //print the current tag read by the reader
377 | void printCurrentTag() {
378 | if (nfcs.rfid[0]<0) println("No tag");
379 | else println(nfcs.rfid[0], ",", nfcs.rfid[1], ",", nfcs.rfid[2], ",", nfcs.rfid[3]);
380 | }
381 |
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagNums/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagNums/.DS_Store
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagNums/data/tagProfile.csv:
--------------------------------------------------------------------------------
1 | UID0,UID1,UID2,UID3,Label,Ttype,Mtype,L1,L2
2 | 136,4,87,200,A,2,1,0.0,0.0
3 | 136,4,72,200,B,2,1,0.0,0.0
4 | 136,4,232,199,C,2,1,0.0,0.0
5 | 136,4,237,199,D,2,1,0.0,0.0
6 | 136,4,21,199,E,2,1,0.0,0.0
7 | 136,4,53,200,F,2,1,0.0,0.0
8 | 136,4,1,199,G,2,1,0.0,0.0
9 | 136,4,58,200,H,2,1,0.0,0.0
10 | 136,4,52,200,I,2,1,0.0,0.0
11 | 136,4,68,200,J,2,1,0.0,0.0
12 | 136,4,16,199,K,2,1,0.0,0.0
13 | 136,4,47,200,L,2,1,0.0,0.0
14 | 136,4,222,199,M,2,1,0.0,0.0
15 | 136,4,242,199,N,2,1,0.0,0.0
16 | 136,4,63,200,O,2,1,0.0,0.0
17 | 136,4,252,199,P,2,1,0.0,0.0
18 | 136,4,77,200,Q,2,1,0.0,0.0
19 | 136,4,227,199,R,2,1,0.0,0.0
20 | 136,4,92,200,S,2,1,0.0,0.0
21 | 136,4,48,200,T,2,1,0.0,0.0
22 | 136,4,247,199,U,2,1,0.0,0.0
23 | 136,4,27,200,V,2,1,0.0,0.0
24 | 136,4,82,200,W,2,1,0.0,0.0
25 | 136,4,31,199,X,2,1,0.0,0.0
26 | 136,4,37,200,Y,2,1,0.0,0.0
27 | 136,4,26,199,Z,2,1,0.0,0.0
28 | 136,4,129,200,0,2,1,0.0,0.0
29 | 136,4,32,200,1,2,1,0.0,0.0
30 | 136,4,126,199,2,2,1,0.0,0.0
31 | 136,4,111,199,3,2,1,0.0,0.0
32 | 136,4,121,199,4,2,1,0.0,0.0
33 | 136,4,116,199,5,2,1,0.0,0.0
34 | 136,4,101,199,6,2,1,0.0,0.0
35 | 136,4,91,199,7,2,1,0.0,0.0
36 | 136,4,96,199,8,2,1,0.0,0.0
37 | 136,4,106,199,9,2,1,0.0,0.0
38 | 136,4,107,200,Apple,2,1,0.0,0.0
39 | 136,4,112,200,2,2,1,0.0,0.0
40 | 136,4,117,200,Carrot,2,1,0.0,0.0
41 | 136,4,22,200,1,2,1,0.0,0.0
42 | 136,4,36,199,3,2,1,0.0,0.0
43 | 136,4,102,200,Banana,2,1,0.0,0.0
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagNums/e1_SingleTagNums.pde:
--------------------------------------------------------------------------------
1 | /*==========================================================================
2 | // OpenNFCSense4P (v2) - Open NFCSense API for Processing Language
3 | // Copyright (C) 2021 Dr. Rong-Hao Liang
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //==========================================================================*/
17 | // e1_SingleTagRotation.pde:
18 | // This software works with a microcontroller running Arduino code and connected to an RC522 NFC/RFID Reader
19 | // OpenNFCSense API Github repository: https://github.com/howieliang/OpenNFCSense
20 | // NFCSense Project website: https://ronghaoliang.page/NFCSense/
21 |
22 | import processing.serial.*;
23 | import OpenNFCSense4P.*;
24 | Serial port;
25 | OpenNFCSense4P nfcs;
26 |
27 | String lastString = "";
28 | String tempString = "";
29 | float lastFreq = 0;
30 | long timer = 0;
31 | boolean bEntered = true;
32 |
33 | String[] QStrings = {"77-65=", "777-654=", "7777-6543="};
34 | String[] AStrings = {"12", "123", "1234"};
35 | int qIndex = 0;
36 | boolean bCorrect = false;
37 |
38 | void setup() {
39 | size(800, 600, P2D); //Start a 800x600 px canvas (using P2D renderer)
40 | //nfcs = new OpenNFCSense4P(this, "tagProfile.csv"); //Initialize OpenNFCSense with the tag profiles (*.csv) in /data
41 | nfcs = new OpenNFCSense4P(this, "tagProfile.csv", 300, 300, 300);
42 | ////set frame rate to 250fps, TTL timer1 to 500ms, and TTL timer2 to 2000ms
43 | initSerial(); //Initialize the serial port
44 | /*== Put your codes below ==*/
45 | /*== Put your codes above ==*/
46 | }
47 |
48 | void draw() {
49 | nfcs.updateNFCBits(); //update the features of current bit
50 | /*== Put your codes below ==*/
51 | ArrayList nbitList = nfcs.getNFCBits();
52 | if (nbitList.size()>0) {
53 | lastString = "";
54 | tempString = "";
55 | for (int i = nbitList.size()-1; i >=0; i--) {
56 | NFCBit nb = nbitList.get(i);
57 | tempString += nb.getName();
58 | }
59 | timer = millis();
60 | bEntered = false;
61 | }
62 | /*== Put your codes above ==*/
63 | background(255); //Refresh the screen
64 | nfcs.drawMotionModeRecords(50, 2*height/3, 2*width/3, height/3-50); //draw the motion mode record of last second (x,y,width,height)
65 | /*== Put your codes below ==*/
66 | if (millis()-timer>100 && bEntered == false) {
67 | lastString = tempString;
68 | bEntered = true;
69 | }
70 | if (millis()-timer>1000) {
71 | if (!lastString.equals("")) {
72 | if(bCorrect){
73 | ++qIndex;
74 | qIndex %= QStrings.length;
75 | lastString = "";
76 | }else{
77 | lastString = "";
78 | }
79 | }
80 | }
81 | if (lastString.equals("")) {
82 | drawString(QStrings[qIndex]+lastString, 50, 100, color(0));
83 | } else {
84 | if (lastString.equals(AStrings[qIndex])) bCorrect = true;
85 | else bCorrect = false;
86 | if(bCorrect) drawString(QStrings[qIndex]+lastString, 50, 100,color(22, 160, 133));
87 | else drawString(QStrings[qIndex]+lastString, 50, 100,color(231, 76, 60));
88 | }
89 | /*== Put your codes above ==*/
90 | drawRecentBits(50, height/4+100); //draw the basic information of the recent NFCBits (within Timer2)
91 | drawInfo(width, height); //draw the version, read rate, and TTL timer info
92 | //printLastBit(); //print the extra information of the last NFCBit in the console
93 | //printCurrentTag(); //print the current tag read by the reader
94 | }
95 |
96 | /*Initialize the serial port*/
97 | void initSerial() {
98 | for (int i = 0; i < Serial.list().length; i++) println("[", i, "]:", Serial.list()[i]); //print the serial port
99 | port = new Serial(this, Serial.list()[Serial.list().length-1], 115200); //for Mac and Linux
100 | // port = new Serial(this, Serial.list()[0], 115200); // for PC
101 | port.bufferUntil('\n'); // arduino ends each data packet with a carriage return
102 | port.clear(); // flush the Serial buffer
103 | }
104 |
105 | /*draw a formatted String*/
106 | void drawString(String s, int x, int y, color c) { //print the latest tag appearance
107 | pushStyle();
108 | fill(c);
109 | textSize(48);
110 | text(s, x, y);
111 | popStyle();
112 | }
113 |
114 | void drawSpeedmeter(float TacoValue, float _x, float _y, float _w, float _h, float _r) {
115 | float blight = 90;
116 | float r = _r;
117 | pushStyle();
118 | colorMode(HSB, 140);
119 | float TacoValueMap = map(TacoValue, 0, 30, -40, 220);
120 | float theta = radians(TacoValueMap);
121 | float x;
122 | float y;
123 | x = -r*cos(theta);
124 | y = -r*sin(theta);
125 |
126 | fill(30, 0, blight);
127 | textAlign(CENTER);
128 | textSize(50);
129 |
130 | pushMatrix();
131 | translate(_x, _y);
132 |
133 | pushMatrix();
134 | translate(_w/2, _h/2);
135 | rotate(-70 * PI / 180);
136 | strokeCap(SQUARE);
137 | strokeWeight(10);
138 | stroke(55, 99, 30);
139 | for (int i = 0; i < 7; i++) {
140 | rotate(40 * PI / 180);
141 | line(-r-10, 0, -r+33, 0);
142 | }
143 | popMatrix();
144 |
145 | pushMatrix();
146 | translate(_w/2, _h/2);
147 | rotate(-70 * PI / 180);
148 | strokeCap(ROUND);
149 | strokeWeight(8);
150 | stroke(55, 80, blight);
151 | for (int i = 0; i < 7; i++) {
152 | rotate(40 * PI / 180);
153 | line(-r-8, 0, -r+32, 0);
154 | }
155 | popMatrix();
156 |
157 | pushMatrix();
158 | translate(_w/2, _h/2);
159 | rotate(-30 * PI / 180);
160 | strokeCap(ROUND);
161 | strokeWeight(4);
162 | stroke(55, 80, blight);
163 | for (int i = 0; i < 24; i++) {
164 | rotate(10 * PI / 180);
165 | line(-r-8, 0, -r+10, 0);
166 | }
167 | popMatrix();
168 |
169 | pushMatrix();
170 | translate(_w/2, _h/2);
171 | rotate(-30 * PI / 180);
172 | strokeCap(ROUND);
173 | strokeWeight(4);
174 | stroke(55, 80, blight);
175 | for (int i = 0; i < 48; i++) {
176 | rotate(5 * PI / 180);
177 | line(-r-8, 0, -r, 0);
178 | }
179 | popMatrix();
180 |
181 | pushMatrix();
182 | translate(_w/2, _h/2);
183 | noFill();
184 | stroke(0, 0, 50);
185 | strokeWeight(15);
186 | stroke(0, 99, 30);
187 | strokeWeight(12);
188 | strokeCap(ROUND);
189 | line(0, 0, x, y);
190 | stroke(0, 99, blight);
191 | strokeWeight(8);
192 | line(0, 0, x, y);
193 | stroke(0, 0, blight);
194 | strokeWeight(6);
195 | line(x/10, y/10, x/5, y/5);
196 | popMatrix();
197 |
198 | stroke(0, 0, 30);
199 | strokeWeight(3);
200 | fill(0, 0, blight);
201 | ellipse(_w/2, _h/2, 44, 44);
202 | popMatrix();
203 | popStyle();
204 | println(TacoValueMap);
205 | }
206 |
207 | /*draw the basic information of the last NFCBit*/
208 | void drawLastBit(int x, int y) { //print the latest tag appearance
209 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
210 | String objInfo = "Current object: ", motionInfo = "";
211 | String tagID = "";
212 | if (nbitList.size()>0) {
213 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
214 | tagID = "["+nfcs.getIDTable().get(0)+"]"; // get the ID string of the latest tag
215 | objInfo += nb.getName();
216 | if (nb.getMode()!=NFCBit.NA) { // if the feature is ready (mode!=NA=0)
217 | if (nb.isFrequency()) { // if the NFCBit is a frequency bit
218 | motionInfo += nb.getModeString()+" at "+nf(nb.getFrequency(), 0, 2)+" Hz"; //show the motion mode and the motion frequency
219 | } else {
220 | motionInfo += nb.getModeString()+" at "+nf(nb.getSpeed(), 0, 2)+" km/h"; //show the motion mode and the motion speed
221 | }
222 | }
223 | }
224 | pushStyle();
225 | fill(0);
226 | textSize(48);
227 | text(objInfo, x, y);
228 | textSize(32);
229 | text(motionInfo, x, y+48);
230 | textSize(16);
231 | text(tagID, x, y+48+32);
232 | popStyle();
233 | }
234 |
235 | /*draw the basic information of the recent NFCBits (within timer 2)*/
236 | void drawRecentBits(int x, int y) {
237 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
238 | ArrayList IDList = nfcs.getIDTable(); // get the ID string of the recent NFCBits
239 | String tagName = "";
240 | String tagID = "";
241 | //for (int i = 0; i < nbitList.size(); i++) { // to reverse the order
242 | for (int i = nbitList.size()-1; i >=0; i--) {
243 | NFCBit nb = nbitList.get(i);
244 | tagName += nb.getName();
245 | tagID += "["+IDList.get(i)+"]";
246 | if (i>0) {
247 | tagName += ", ";
248 | tagID += ", ";
249 | }
250 | }
251 | pushStyle();
252 | fill(0);
253 | textSize(48);
254 | text("Recent objects: ", x, y);
255 | textSize(32);
256 | text(tagName, x, y+48);
257 | textSize(16);
258 | text(tagID, x, y+48+32);
259 | popStyle();
260 | }
261 |
262 | /*draw the version, read rate, and TTL timer info*/
263 | void drawInfo(int x, int y) {
264 | String info = "[Open NFCSense] ver. "+OpenNFCSense4P.version()+"\n"; //get the current library version
265 | info += "Read rate: "+nf(nfcs.getReadRate(), 0, 0)+" reads/sec\n"; // get the current read rate
266 | info += "TTL Timer1: "+nf(nfcs.getTimer1(), 0, 0)+" ms\n"; // get the current TTL timer1
267 | info += "TTL Timer2: "+nf(nfcs.getTimer2(), 0, 0)+" ms"; // get the current TTL timer2
268 | //set the above parameters in the constructor as indicated in setup();
269 | pushStyle();
270 | fill(100);
271 | textSize(12);
272 | textAlign(RIGHT, BOTTOM);
273 | text(info, x-5, y-5);
274 | popStyle();
275 | }
276 |
277 | /*print the extra information of the recent NFCBits in the console*/
278 | void printRecentBits() {
279 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
280 | for (int i = 0; i < nbitList.size(); i++) {
281 | NFCBit nb = nbitList.get(i); // get the latest NFCBit at index i
282 | String tagID = "["+nfcs.getIDTable().get(i)+"]"; //get the ID string of the latest tag
283 | print("[", i, "]", tagID, nb.getName(), ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
284 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
285 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
286 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
287 | //the type of motion (e.g., linear translation, rotation, shm, compound+motion)
288 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
289 | //the features (speed and frequency)
290 | }
291 | println("===");
292 | }
293 |
294 | /*print the extra information of the last NFCBit in the console*/
295 | void printLastBit() {
296 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
297 | if (nbitList.size()>0) {
298 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
299 | String tagID = "["+nfcs.getIDTable().get(0)+"]"; //get the ID string of the latest tag
300 | print(nb.getName(), tagID, ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
301 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
302 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
303 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
304 | //the type of motion (e.g., linear translation, rotation, shm, compound, compound+motion)
305 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
306 | //the features (speed and frequency)
307 | }
308 | println("===");
309 | }
310 |
311 | /*The serial event handler processes the data from any NFC reader in the String format of
312 | // "A[Byte_0]\n, B[Byte_1]\n, C[Byte_2]\n, or D[Byte_3]\n",
313 | //where every byte is an unsigned integer ranged between [0-256].
314 | //When a tag is present: Byte_i=[0-255]; Otherwise, when a tag is absent: [256].
315 | //================*/
316 |
317 | void serialEvent(Serial port) {
318 | String inData = port.readStringUntil('\n'); // read the serial string until seeing a carriage return
319 | if (inData.charAt(0) >= 'A' && inData.charAt(0) <= 'D') {
320 | int i = inData.charAt(0)-'A';
321 | int v = int(trim(inData.substring(1)));
322 | nfcs.rfid[i] = (v>255?-1:v);
323 | if (i==3) nfcs.checkTagID(); // process the tag ID when a sequence is collected completely.
324 | }
325 | return;
326 | }
327 |
328 | //print the current tag read by the reader
329 | void printCurrentTag() {
330 | if (nfcs.rfid[0]<0) println("No tag");
331 | else println(nfcs.rfid[0], ",", nfcs.rfid[1], ",", nfcs.rfid[2], ",", nfcs.rfid[3]);
332 | }
333 |
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagSelfDefined/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagSelfDefined/.DS_Store
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagSelfDefined/data/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagSelfDefined/data/.DS_Store
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagSelfDefined/data/apple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagSelfDefined/data/apple.png
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagSelfDefined/data/banana.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagSelfDefined/data/banana.png
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagSelfDefined/data/carrot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/examples/episode2/e1_SingleTagSelfDefined/data/carrot.png
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagSelfDefined/data/tagProfile.csv:
--------------------------------------------------------------------------------
1 | UID0,UID1,UID2,UID3,Label,Ttype,Mtype,L1,L2
2 | 136,4,87,200,A,2,1,0.0,0.0
3 | 136,4,72,200,B,2,1,0.0,0.0
4 | 136,4,232,199,C,2,1,0.0,0.0
5 | 136,4,237,199,D,2,1,0.0,0.0
6 | 136,4,21,199,E,2,1,0.0,0.0
7 | 136,4,53,200,F,2,1,0.0,0.0
8 | 136,4,1,199,G,2,1,0.0,0.0
9 | 136,4,58,200,H,2,1,0.0,0.0
10 | 136,4,52,200,I,2,1,0.0,0.0
11 | 136,4,68,200,J,2,1,0.0,0.0
12 | 136,4,16,199,K,2,1,0.0,0.0
13 | 136,4,47,200,L,2,1,0.0,0.0
14 | 136,4,222,199,M,2,1,0.0,0.0
15 | 136,4,242,199,N,2,1,0.0,0.0
16 | 136,4,63,200,O,2,1,0.0,0.0
17 | 136,4,252,199,P,2,1,0.0,0.0
18 | 136,4,77,200,Q,2,1,0.0,0.0
19 | 136,4,227,199,R,2,1,0.0,0.0
20 | 136,4,92,200,S,2,1,0.0,0.0
21 | 136,4,48,200,T,2,1,0.0,0.0
22 | 136,4,247,199,U,2,1,0.0,0.0
23 | 136,4,27,200,V,2,1,0.0,0.0
24 | 136,4,82,200,W,2,1,0.0,0.0
25 | 136,4,31,199,X,2,1,0.0,0.0
26 | 136,4,37,200,Y,2,1,0.0,0.0
27 | 136,4,26,199,Z,2,1,0.0,0.0
28 | 136,4,129,200,0,2,1,0.0,0.0
29 | 136,4,32,200,1,2,1,0.0,0.0
30 | 136,4,126,199,2,2,1,0.0,0.0
31 | 136,4,111,199,3,2,1,0.0,0.0
32 | 136,4,121,199,4,2,1,0.0,0.0
33 | 136,4,116,199,5,2,1,0.0,0.0
34 | 136,4,101,199,6,2,1,0.0,0.0
35 | 136,4,91,199,7,2,1,0.0,0.0
36 | 136,4,96,199,8,2,1,0.0,0.0
37 | 136,4,106,199,9,2,1,0.0,0.0
38 | 136,4,107,200,Apple,2,1,0.0,0.0
39 | 136,4,112,200,2,2,1,0.0,0.0
40 | 136,4,117,200,Carrot,2,1,0.0,0.0
41 | 136,4,22,200,1,2,1,0.0,0.0
42 | 136,4,36,199,3,2,1,0.0,0.0
43 | 136,4,102,200,Banana,2,1,0.0,0.0
44 | 136,4,121,150,power2,2,1,0.0,0.0
45 | 136,4,130,150,power3,2,1,0.0,0.0
46 | 136,4,129,150,for,2,1,0.0,0.0
47 | 136,4,146,150,while,2,1,0.0,0.0
--------------------------------------------------------------------------------
/examples/episode2/e1_SingleTagSelfDefined/e1_SingleTagSelfDefined.pde:
--------------------------------------------------------------------------------
1 | /*==========================================================================
2 | // OpenNFCSense4P (v2) - Open NFCSense API for Processing Language
3 | // Copyright (C) 2021 Dr. Rong-Hao Liang
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //==========================================================================*/
17 | // e1_SingleTagRotation.pde:
18 | // This software works with a microcontroller running Arduino code and connected to an RC522 NFC/RFID Reader
19 | // OpenNFCSense API Github repository: https://github.com/howieliang/OpenNFCSense
20 | // NFCSense Project website: https://ronghaoliang.page/NFCSense/
21 |
22 | import processing.serial.*;
23 | import OpenNFCSense4P.*;
24 | Serial port;
25 | OpenNFCSense4P nfcs;
26 |
27 | String lastString = "";
28 | String tempString = "";
29 | long timer = 0;
30 | boolean bEntered = true;
31 |
32 | String[] QStrings = {"16 = ", "9 = ", "27 = "};
33 | String[] AStrings = {"4C", "3C", "3D"};
34 | int qIndex = 0;
35 | boolean bCorrect = false;
36 |
37 | PImage[] img = new PImage[3];
38 | int pw;
39 |
40 | void setup() {
41 | size(800, 600, P2D); //Start a 800x600 px canvas (using P2D renderer)
42 | //nfcs = new OpenNFCSense4P(this, "tagProfile.csv"); //Initialize OpenNFCSense with the tag profiles (*.csv) in /data
43 | nfcs = new OpenNFCSense4P(this, "tagProfile.csv", 300, 300, 300);
44 | ////set frame rate to 250fps, TTL timer1 to 500ms, and TTL timer2 to 2000ms
45 | initSerial(); //Initialize the serial port
46 | /*== Put your codes below ==*/
47 | /*== Put your codes above ==*/
48 | }
49 |
50 | void draw() {
51 | nfcs.updateNFCBits(); //update the features of current bit
52 | /*== Put your codes below ==*/
53 | ArrayList nbitList = nfcs.getNFCBits();
54 | if (nbitList.size()>0) {
55 | lastString = "";
56 | tempString = "";
57 | for (int i = nbitList.size()-1; i >=0; i--) {
58 | NFCBit nb = nbitList.get(i);
59 | if (nb.getName().equals("power2")) tempString += "C";
60 | else if (nb.getName().equals("power3")) tempString += "D";
61 | else tempString += nb.getName();
62 | }
63 | timer = millis();
64 | bEntered = false;
65 | }
66 | /*== Put your codes above ==*/
67 | background(255); //Refresh the screen
68 | nfcs.drawMotionModeRecords(50, 2*height/3, 2*width/3, height/3-50); //draw the motion mode record of last second (x,y,width,height)
69 | /*== Put your codes below ==*/
70 | if (millis()-timer>100 && bEntered == false) {
71 | lastString = tempString;
72 | bEntered = true;
73 | }
74 | if (millis()-timer>2000) {
75 | if (!lastString.equals("")) {
76 | if (bCorrect) {
77 | ++qIndex;
78 | qIndex %= QStrings.length;
79 | lastString = "";
80 | } else {
81 | lastString = "";
82 | }
83 | }
84 | }
85 | if (lastString.equals("")) {
86 | drawString(QStrings[qIndex]+lastString, 50, 100, color(0));
87 | } else {
88 | if (lastString.equals(AStrings[qIndex])) bCorrect = true;
89 | else bCorrect = false;
90 | if (bCorrect) {
91 | if (lastString.length()>=2) {
92 | int n1 = lastString.charAt(0)-'0';
93 | int o1 = lastString.charAt(1)-'A';
94 | drawString(QStrings[qIndex]+n1+(o1==2?'\u00B2':'\u00B3'), 50, 100, color(22, 160, 133));
95 | }
96 | } else {
97 | if (lastString.length()>=2) {
98 | int n1 = lastString.charAt(0)-'0';
99 | int o1 = lastString.charAt(1)-'A';
100 | drawString(QStrings[qIndex]+n1+(o1==2?'\u00B2':'\u00B3'), 50, 100, color(231, 76, 60));
101 | }
102 | }
103 | }
104 | /*== Put your codes above ==*/
105 | drawRecentBits(50, height/4+100); //draw the basic information of the recent NFCBits (within Timer2)
106 | drawInfo(width, height); //draw the version, read rate, and TTL timer info
107 | //printLastBit(); //print the extra information of the last NFCBit in the console
108 | printCurrentTag(); //print the current tag read by the reader
109 | }
110 |
111 | /*Initialize the serial port*/
112 | void initSerial() {
113 | for (int i = 0; i < Serial.list().length; i++) println("[", i, "]:", Serial.list()[i]); //print the serial port
114 | port = new Serial(this, Serial.list()[Serial.list().length-1], 115200); //for Mac and Linux
115 | // port = new Serial(this, Serial.list()[0], 115200); // for PC
116 | port.bufferUntil('\n'); // arduino ends each data packet with a carriage return
117 | port.clear(); // flush the Serial buffer
118 | }
119 |
120 | /*draw a formatted String*/
121 | void drawString(String s, int x, int y, color c) { //print the latest tag appearance
122 | pushStyle();
123 | textAlign(LEFT, TOP);
124 | fill(c);
125 | textSize(48);
126 | text(s, x, y);
127 | popStyle();
128 | }
129 |
130 | void drawSpeedmeter(float TacoValue, float _x, float _y, float _w, float _h, float _r) {
131 | float blight = 90;
132 | float r = _r;
133 | pushStyle();
134 | colorMode(HSB, 140);
135 | float TacoValueMap = map(TacoValue, 0, 30, -40, 220);
136 | float theta = radians(TacoValueMap);
137 | float x;
138 | float y;
139 | x = -r*cos(theta);
140 | y = -r*sin(theta);
141 |
142 | fill(30, 0, blight);
143 | textAlign(CENTER);
144 | textSize(50);
145 |
146 | pushMatrix();
147 | translate(_x, _y);
148 |
149 | pushMatrix();
150 | translate(_w/2, _h/2);
151 | rotate(-70 * PI / 180);
152 | strokeCap(SQUARE);
153 | strokeWeight(10);
154 | stroke(55, 99, 30);
155 | for (int i = 0; i < 7; i++) {
156 | rotate(40 * PI / 180);
157 | line(-r-10, 0, -r+33, 0);
158 | }
159 | popMatrix();
160 |
161 | pushMatrix();
162 | translate(_w/2, _h/2);
163 | rotate(-70 * PI / 180);
164 | strokeCap(ROUND);
165 | strokeWeight(8);
166 | stroke(55, 80, blight);
167 | for (int i = 0; i < 7; i++) {
168 | rotate(40 * PI / 180);
169 | line(-r-8, 0, -r+32, 0);
170 | }
171 | popMatrix();
172 |
173 | pushMatrix();
174 | translate(_w/2, _h/2);
175 | rotate(-30 * PI / 180);
176 | strokeCap(ROUND);
177 | strokeWeight(4);
178 | stroke(55, 80, blight);
179 | for (int i = 0; i < 24; i++) {
180 | rotate(10 * PI / 180);
181 | line(-r-8, 0, -r+10, 0);
182 | }
183 | popMatrix();
184 |
185 | pushMatrix();
186 | translate(_w/2, _h/2);
187 | rotate(-30 * PI / 180);
188 | strokeCap(ROUND);
189 | strokeWeight(4);
190 | stroke(55, 80, blight);
191 | for (int i = 0; i < 48; i++) {
192 | rotate(5 * PI / 180);
193 | line(-r-8, 0, -r, 0);
194 | }
195 | popMatrix();
196 |
197 | pushMatrix();
198 | translate(_w/2, _h/2);
199 | noFill();
200 | stroke(0, 0, 50);
201 | strokeWeight(15);
202 | stroke(0, 99, 30);
203 | strokeWeight(12);
204 | strokeCap(ROUND);
205 | line(0, 0, x, y);
206 | stroke(0, 99, blight);
207 | strokeWeight(8);
208 | line(0, 0, x, y);
209 | stroke(0, 0, blight);
210 | strokeWeight(6);
211 | line(x/10, y/10, x/5, y/5);
212 | popMatrix();
213 |
214 | stroke(0, 0, 30);
215 | strokeWeight(3);
216 | fill(0, 0, blight);
217 | ellipse(_w/2, _h/2, 44, 44);
218 | popMatrix();
219 | popStyle();
220 | println(TacoValueMap);
221 | }
222 |
223 | /*draw the basic information of the last NFCBit*/
224 | void drawLastBit(int x, int y) { //print the latest tag appearance
225 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
226 | String objInfo = "Current object: ", motionInfo = "";
227 | String tagID = "";
228 | if (nbitList.size()>0) {
229 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
230 | tagID = "["+nfcs.getIDTable().get(0)+"]"; // get the ID string of the latest tag
231 | objInfo += nb.getName();
232 | if (nb.getMode()!=NFCBit.NA) { // if the feature is ready (mode!=NA=0)
233 | if (nb.isFrequency()) { // if the NFCBit is a frequency bit
234 | motionInfo += nb.getModeString()+" at "+nf(nb.getFrequency(), 0, 2)+" Hz"; //show the motion mode and the motion frequency
235 | } else {
236 | motionInfo += nb.getModeString()+" at "+nf(nb.getSpeed(), 0, 2)+" km/h"; //show the motion mode and the motion speed
237 | }
238 | }
239 | }
240 | pushStyle();
241 | fill(0);
242 | textSize(48);
243 | text(objInfo, x, y);
244 | textSize(32);
245 | text(motionInfo, x, y+48);
246 | textSize(16);
247 | text(tagID, x, y+48+32);
248 | popStyle();
249 | }
250 |
251 | /*draw the basic information of the recent NFCBits (within timer 2)*/
252 | void drawRecentBits(int x, int y) {
253 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
254 | ArrayList IDList = nfcs.getIDTable(); // get the ID string of the recent NFCBits
255 | String tagName = "";
256 | String tagID = "";
257 | //for (int i = 0; i < nbitList.size(); i++) { // to reverse the order
258 | for (int i = nbitList.size()-1; i >=0; i--) {
259 | NFCBit nb = nbitList.get(i);
260 | tagName += nb.getName();
261 | tagID += "["+IDList.get(i)+"]";
262 | if (i>0) {
263 | tagName += ", ";
264 | tagID += ", ";
265 | }
266 | }
267 | pushStyle();
268 | fill(0);
269 | textSize(48);
270 | text("Recent objects: ", x, y);
271 | textSize(32);
272 | text(tagName, x, y+48);
273 | textSize(16);
274 | text(tagID, x, y+48+32);
275 | popStyle();
276 | }
277 |
278 | /*draw the version, read rate, and TTL timer info*/
279 | void drawInfo(int x, int y) {
280 | String info = "[Open NFCSense] ver. "+OpenNFCSense4P.version()+"\n"; //get the current library version
281 | info += "Read rate: "+nf(nfcs.getReadRate(), 0, 0)+" reads/sec\n"; // get the current read rate
282 | info += "TTL Timer1: "+nf(nfcs.getTimer1(), 0, 0)+" ms\n"; // get the current TTL timer1
283 | info += "TTL Timer2: "+nf(nfcs.getTimer2(), 0, 0)+" ms"; // get the current TTL timer2
284 | //set the above parameters in the constructor as indicated in setup();
285 | pushStyle();
286 | fill(100);
287 | textSize(12);
288 | textAlign(RIGHT, BOTTOM);
289 | text(info, x-5, y-5);
290 | popStyle();
291 | }
292 |
293 | /*print the extra information of the recent NFCBits in the console*/
294 | void printRecentBits() {
295 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
296 | for (int i = 0; i < nbitList.size(); i++) {
297 | NFCBit nb = nbitList.get(i); // get the latest NFCBit at index i
298 | String tagID = "["+nfcs.getIDTable().get(i)+"]"; //get the ID string of the latest tag
299 | print("[", i, "]", tagID, nb.getName(), ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
300 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
301 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
302 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
303 | //the type of motion (e.g., linear translation, rotation, shm, compound+motion)
304 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
305 | //the features (speed and frequency)
306 | }
307 | println("===");
308 | }
309 |
310 | /*print the extra information of the last NFCBit in the console*/
311 | void printLastBit() {
312 | ArrayList nbitList = nfcs.getNFCBits(); // get all of the recent NFCBits
313 | if (nbitList.size()>0) {
314 | NFCBit nb = nbitList.get(0); // get the latest NFCBit
315 | String tagID = "["+nfcs.getIDTable().get(0)+"]"; //get the ID string of the latest tag
316 | print(nb.getName(), tagID, ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
317 | //print the name of tag, the ID, the mode of motion depending on the motion type (mode=0: not ready), determined by the m and n in the algorithm.
318 | print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
319 | //print the type of token (e.g., zz*, theta>theta*, d_gap>d_gap*)
320 | //the type of motion (e.g., linear translation, rotation, shm, compound, compound+motion)
321 | println("V=", nf(nb.getSpeed(), 0, 2), "km/h; f=", nf(nb.getFrequency(), 0, 2), "Hz");
322 | //the features (speed and frequency)
323 | }
324 | println("===");
325 | }
326 |
327 | /*The serial event handler processes the data from any NFC reader in the String format of
328 | // "A[Byte_0]\n, B[Byte_1]\n, C[Byte_2]\n, or D[Byte_3]\n",
329 | //where every byte is an unsigned integer ranged between [0-256].
330 | //When a tag is present: Byte_i=[0-255]; Otherwise, when a tag is absent: [256].
331 | //================*/
332 |
333 | void serialEvent(Serial port) {
334 | String inData = port.readStringUntil('\n'); // read the serial string until seeing a carriage return
335 | if (inData.charAt(0) >= 'A' && inData.charAt(0) <= 'D') {
336 | int i = inData.charAt(0)-'A';
337 | int v = int(trim(inData.substring(1)));
338 | nfcs.rfid[i] = (v>255?-1:v);
339 | if (i==3) nfcs.checkTagID(); // process the tag ID when a sequence is collected completely.
340 | }
341 | return;
342 | }
343 |
344 | //print the current tag read by the reader
345 | void printCurrentTag() {
346 | if (nfcs.rfid[0]<0) println("No tag");
347 | else println(nfcs.rfid[0], ",", nfcs.rfid[1], ",", nfcs.rfid[2], ",", nfcs.rfid[3]);
348 | }
349 |
--------------------------------------------------------------------------------
/figures/hardware.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/figures/hardware.png
--------------------------------------------------------------------------------
/figures/playlist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/figures/playlist.png
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howieliang/OpenNFCSense/54d46c78eeea5ab69c925fb5cd67e82963c019ba/src/.DS_Store
--------------------------------------------------------------------------------
/src/OpenNFCSense4P/NFCBit.java:
--------------------------------------------------------------------------------
1 | /*==========================================================================
2 | // OpenNFCSense4P (v1) - Open NFCSense API for Processing Language
3 | // Copyright (C) 2021 Dr. Rong-Hao Liang
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //==========================================================================*/
17 | // This software works with a microcontroller connected to an RC522 NFC/RFID Reader
18 | // and run the Arduino code
19 | // Github repository: https://github.com/howieliang/NFCSense
20 | // Project website: https://ronghaoliang.page/NFCSense/
21 |
22 | package OpenNFCSense4P;
23 |
24 | import java.util.ArrayList;
25 |
26 | //##NFCBits
27 | public class NFCBit {
28 | final public static int NA = 0;
29 | final public static int BELOW_Z_STAR = 1;
30 | final public static int ABOVE_Z_STAR = 2;
31 | final public static int ABOVE_THETA_STAR = 3;
32 |
33 | final public static int L_MOTION = 1;
34 | final public static int ROTATION = 2;
35 | final public static int SHM = 3;
36 | final public static int COMPOUND_R1 = 4;
37 | final public static int COMPOUND_R2 = 5;
38 | final public static int COMPOUND_R3 = 6;
39 | final public static int COMPOUND_L1 = 7;
40 | final public static int COMPOUND_L2 = 8;
41 |
42 | int tokenType = ABOVE_Z_STAR; //default
43 | int motionType = ROTATION; //default
44 | float[] l_onArray = new float[]{44};
45 | String[] stateStrArray = new String[]{"default"};
46 | String[] modeStringArray = new String[]{""};
47 | String[] tTypeStringArray = new String[]{"","zz*","theta>theta*"};
48 | String[] mTypeStringArray = new String[]{"","linear motion","rotation","s.h.m.",
49 | "compound_r1","compound_r2","compound_r3","compound_l1","compound_l2"};
50 |
51 | ArrayList profile = new ArrayList();
52 | int n=0, m=0;
53 | float t_I=0, t_IBI=0, t_M=0, f=0, V=0;
54 | int mode=NA;
55 |
56 | NFCBit() {
57 | //apply all default settings
58 | }
59 |
60 | NFCBit(int tType, int mType) {
61 | tokenType = tType;
62 | motionType = mType;
63 | }
64 |
65 | NFCBit(int tType, int mType, float[] la, String[] sa) {
66 | tokenType = tType;
67 | motionType = mType;
68 | l_onArray = la;
69 | stateStrArray = sa;
70 | }
71 |
72 | void reset() {
73 | n=0;
74 | m=0;
75 | t_I=0;
76 | t_IBI=0;
77 | t_M=0;
78 | f=0;
79 | V=0;
80 | mode=NA;
81 | profile.clear();
82 | }
83 | void getInfo() {
84 | //implemented by the extended classes
85 | }
86 |
87 | void printInfo() {
88 | //implemented by the extended classes
89 | }
90 |
91 | void getFeatures(int lastType) {
92 | //implemented by the extended classes
93 | }
94 |
95 | void setTokenType(int tType) {
96 | tokenType = tType;
97 | }
98 | void setMotionType(int mType) {
99 | motionType = mType;
100 | }
101 | void setL_onArray(float[] la) {
102 | l_onArray = la;
103 | }
104 | void setStateStrArray(String[] sa) {
105 | stateStrArray = sa;
106 | }
107 | float[] getL_onArray() {
108 | return l_onArray;
109 | }
110 | String[] getStateStrArray() {
111 | return stateStrArray;
112 | }
113 |
114 | public boolean isFrequency() {
115 | if (motionType == ROTATION || motionType == SHM || motionType == COMPOUND_R1 || motionType == COMPOUND_R2 || motionType == COMPOUND_R3)
116 | return true;
117 | else
118 | return false;
119 | }
120 | public boolean isSpeed() {
121 | if (motionType == ROTATION || motionType == SHM || motionType == COMPOUND_R1 || motionType == COMPOUND_R2 || motionType == COMPOUND_R3)
122 | return false;
123 | else
124 | return true;
125 | }
126 | public String getName() {
127 | return stateStrArray[0];
128 | }
129 | public float getFrequency() {
130 | return f;
131 | }
132 | public float getSpeed() {
133 | return V;
134 | }
135 | public float getNumOfSegments() {
136 | return n;
137 | }
138 | public float getMainComponentIndex() {
139 | return m;
140 | }
141 | public int getMode() {
142 | return mode;
143 | }
144 | public String getModeString() {
145 | return modeStringArray[mode];
146 | }
147 | public int getTokenType() {
148 | return tokenType;
149 | }
150 | public String getTokenTypeString() {
151 | return tTypeStringArray[tokenType];
152 | }
153 | public int getMotionType() {
154 | return motionType;
155 | }
156 | public String getMotionTypeString() {
157 | return mTypeStringArray[motionType];
158 | }
159 | }
--------------------------------------------------------------------------------
/src/OpenNFCSense4P/OpenNFCSense4P.java:
--------------------------------------------------------------------------------
1 | /*==========================================================================
2 | // OpenNFCSense4P (v1) - Open NFCSense API for Processing Language
3 | // Copyright (C) 2021 Dr. Rong-Hao Liang
4 | // This program is free software: you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation, either version 3 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program. If not, see .
16 | //==========================================================================*/
17 | // This software works with a microcontroller connected to an RC522 NFC/RFID Reader
18 | // and run the Arduino code
19 | // Github repository: https://github.com/howieliang/NFCSense
20 | // Project website: https://ronghaoliang.page/NFCSense/
21 |
22 | package OpenNFCSense4P;
23 |
24 | import java.util.ArrayList;
25 |
26 | import processing.core.*;
27 | import processing.data.*;
28 |
29 | /**
30 | * OpenNFCSense
31 | *
32 | * @example Hello
33 | */
34 |
35 | public class OpenNFCSense4P implements PConstants {
36 |
37 | // pa is a reference to the parent sketch
38 | PApplet pa;
39 | public final static String VERSION = "##library.prettyVersion##";
40 |
41 | final int IDBitNum = 4;
42 | final int MotionTypeNum = 8;
43 |
44 | float SAMPLE_RATE = 300.0f; // reads per second
45 | float TTL1_THLD = 300.0f; //ttl_timer 1 threshold
46 | float TTL2_THLD = 1000.0f; //ttl_timer 2 threshold
47 |
48 | boolean DEBUG_ID = false;
49 | boolean DEBUG_TIMER = false;
50 |
51 | int idNum = 0;
52 | ArrayList id_db = new ArrayList();
53 |
54 |
55 | public int[] rfid = new int[IDBitNum];
56 | int[] lastRFID = new int[IDBitNum];
57 |
58 | int[] ibiCounter, tOnCounter, ibiLastEventTS;
59 | float[] lastIBI;
60 | float[][] idArray, mTypeArray, idSCntArray, tOnCntrArray;
61 |
62 | public float[][] RFIDHist;
63 | int streamSize = (int) SAMPLE_RATE;
64 | float[] modeArray = new float[streamSize];
65 | float[] eventArray = new float[streamSize];
66 | ArrayList lastIDList;
67 |
68 | // GLOBAL Variables
69 | public int lastRead = -1; // GLOBAL variable of last read.
70 | public int lastID = -1; // GLOBAL. Only for control.
71 | public int lastIDIndex = -1;
72 | public String IDModeString = "";
73 | public String lastIDString = "";
74 | public int ts = 0;
75 | public boolean profileReady = false;
76 | public int colNum = 3;
77 | public int gH, gW;
78 | public String[] fontList;
79 | public int fontSize = 24;
80 | public int tSize = 64;
81 | public PFont font;
82 |
83 | // TTL timers
84 | int last_t1 = 0;
85 | int last_t2 = 0;
86 | int ttl1 = 0;
87 | int ttl2 = 0;
88 |
89 |
90 | // Container
91 | ArrayList nbits;
92 |
93 | /**
94 | * OpenNFCSense Constructor
95 | *
96 | * @param theParent the parent PApplet
97 | */
98 | public OpenNFCSense4P(PApplet theParent, String fileName) {
99 | pa = theParent;
100 | initNFCBits(fileName);
101 | welcome();
102 | }
103 |
104 | public OpenNFCSense4P(PApplet theParent, String fileName, float sample_rate) {
105 | pa = theParent;
106 | initNFCBits(fileName);
107 | SAMPLE_RATE = sample_rate;
108 | welcome();
109 | }
110 |
111 | public OpenNFCSense4P(PApplet theParent, String fileName, float sample_rate, int timer1, int timer2) {
112 | pa = theParent;
113 | initNFCBits(fileName);
114 | SAMPLE_RATE = sample_rate;
115 | TTL1_THLD = timer1; //ttl_timer 1 threshold
116 | TTL2_THLD = timer2; //ttl_timer 2 threshold
117 | welcome();
118 | }
119 |
120 | private void welcome() {
121 | System.out.println("##library.name## ##library.prettyVersion## by ##author##");
122 | }
123 |
124 | /**
125 | * return the version of the Library.
126 | *
127 | * @return String
128 | */
129 | public static String version() {
130 | return VERSION;
131 | }
132 |
133 | public void pre() {
134 | // updateNFCBits();
135 | }
136 |
137 | // ##Init
138 | void initNFCBits(String fileName) {
139 | Table csvData = pa.loadTable(fileName, "header");
140 | nbits = new ArrayList();
141 | if (csvData != null) {
142 | int n = csvData.getRowCount();
143 | // ArrayList uids = new ArrayList();
144 | for (int r = 0; r < n; r++) {
145 | TableRow newRow = csvData.getRow(r);
146 | int uid0 = newRow.getInt("UID0");
147 | int uid1 = newRow.getInt("UID1");
148 | int uid2 = newRow.getInt("UID2");
149 | int uid3 = newRow.getInt("UID3");
150 | String tagName = newRow.getString("Label");
151 | int tType = newRow.getInt("Ttype");
152 | int mType = newRow.getInt("Mtype");
153 | float lon1 = newRow.getFloat("L1");
154 | float lon2 = newRow.getFloat("L2");
155 | int[] _rfid = { uid0, uid1, uid2, uid3, 0 };
156 | id_db.add(IDtoLong(_rfid));
157 |
158 | if (tType == NFCBit.BELOW_Z_STAR && mType == NFCBit.L_MOTION) {
159 | nbits.add(new NFCBitB(new float[] { lon1, lon2 }, new String[] { tagName }));
160 | }
161 | if (tType == NFCBit.ABOVE_THETA_STAR && mType == NFCBit.L_MOTION) {
162 | nbits.add(new NFCBitT(new float[] { lon1, lon2 }, new String[] { tagName }));
163 | }
164 | if (tType == NFCBit.ABOVE_Z_STAR && mType == NFCBit.L_MOTION) {
165 | nbits.add(new NFCBitAL(new float[] { lon1, lon2 }, new String[] { tagName }));
166 | }
167 | if (tType == NFCBit.ABOVE_Z_STAR && mType == NFCBit.ROTATION) {
168 | nbits.add(new NFCBitAR(new float[] { lon1, lon2 }, new String[] { tagName }));
169 | }
170 | if (tType == NFCBit.ABOVE_Z_STAR && mType == NFCBit.SHM) {
171 | nbits.add(new NFCBitAS(new float[] { lon1, lon2 }, new String[] { tagName }));
172 | }
173 | if (mType == NFCBit.COMPOUND_R1 || mType == NFCBit.COMPOUND_R2 || mType == NFCBit.COMPOUND_R3) {
174 | nbits.add(new NFCBitCR(new float[] { lon1, lon2 }, new String[] { tagName }, mType));
175 | }
176 | if (mType == NFCBit.COMPOUND_L1 || mType == NFCBit.COMPOUND_L2) {
177 | nbits.add(new NFCBitCL(new float[] { lon1, lon2 }, new String[] { tagName }, mType));
178 | }
179 | }
180 | }
181 |
182 | initParam();
183 | }
184 |
185 | void initParam() {
186 | fontList = PFont.list();
187 | font = pa.createFont("Lucida Sans Regular", 72);
188 | pa.textFont(font);
189 | gH = pa.height;
190 | gW = pa.width;
191 | last_t1 = pa.millis();
192 | last_t2 = pa.millis();
193 |
194 | idNum = id_db.size(); // new
195 | lastIDList = new ArrayList();
196 |
197 | ibiCounter = new int[idNum];
198 | tOnCounter = new int[idNum];
199 | ibiLastEventTS = new int[idNum];
200 | lastIBI = new float[idNum];
201 |
202 | rfid = new int[IDBitNum];
203 | lastRFID = new int[IDBitNum];
204 | idSCntArray = new float[idNum][streamSize]; // history data to show
205 | tOnCntrArray = new float[idNum][streamSize]; // history data to show
206 |
207 | // RFIDHist = new float[IDBitNum][streamSize]; //history data to show
208 | idArray = new float[idNum][streamSize];
209 | mTypeArray = new float[MotionTypeNum][streamSize];
210 | modeArray = new float[streamSize]; // To show activated or not
211 | eventArray = new float[streamSize]; // To show activated or not
212 |
213 | for (int i = 0; i < idNum; i++) {
214 | for (int j = 0; j < streamSize; j++) {
215 | idArray[i][j] = -1; // history data to show
216 | }
217 | tOnCounter[i] = 0;
218 | ibiLastEventTS[i] = 0;
219 | }
220 |
221 | for (int i = 0; i < MotionTypeNum; i++) {
222 | for (int j = 0; j < streamSize; j++) {
223 | mTypeArray[i][j] = -1; // history data to show
224 | }
225 | }
226 |
227 | for (int i = 0; i < streamSize; i++) {
228 | modeArray[i] = -1;
229 | eventArray[i] = -1;
230 | }
231 |
232 | for (int i = 0; i < IDBitNum; i++) {
233 | rfid[i] = -1;
234 | lastRFID[i] = -1;
235 | }
236 |
237 | lastIDString = "";
238 | lastIDIndex = -1;
239 | ts = 0;
240 | }
241 |
242 | // ##Draw
243 |
244 | void drawIDInfo(String str) {
245 | if (str == "")
246 | showInfo("Waiting for the first tag...", gW / 2, 20, 20);
247 | else
248 | showInfo("Last Tag: " + str + " is recognized as:", gW / 2, 20, 20);
249 | }
250 |
251 | void drawLMotionSignals(int n) {
252 | lineGraph2(tOnCntrArray[n], 300, 0, 0, 2 * gH / colNum, gW, gH / (colNum * 2), n); // history of signal
253 | barGraph(modeArray, 0, 3 * gH / colNum, gW, gH / (colNum * 2));
254 | }
255 |
256 | void drawRotationSignals(int n) {
257 | lineGraph2(idSCntArray[n], 20, 0, 0, 2 * gH / colNum, gW, gH / colNum, n); // history of signal
258 | }
259 |
260 | void drawSHMSignals(int n) {
261 | lineGraph2(tOnCntrArray[n], 300, 0, 0, 2 * gH / colNum, gW, gH / colNum, n); // history of signal
262 | }
263 |
264 | void drawIDStream(int n) {
265 | barGraph(idArray[n], 0, 2 * gH / colNum - n * gH / (colNum * idNum), gW, gH / (colNum * idNum), n); // history
266 | // of signal
267 | }
268 |
269 | public void drawResults() {
270 | pa.pushStyle();
271 | drawIDInfo(lastIDString);
272 | for (int n = 0; n < idNum; n++) {
273 | NFCBit nb = nbits.get(n);
274 | int mType = nb.getMotionType();
275 | drawIDStream(n);
276 | if (lastIDIndex == n && IDModeString.length() > 0) {
277 | switch (mType) {
278 | case NFCBit.L_MOTION:
279 | drawLMotionSignals(n);
280 | if (profileReady) {
281 | nb.getInfo();
282 | }
283 | break;
284 | case NFCBit.ROTATION:
285 | drawRotationSignals(n);
286 | nb.getInfo();
287 | break;
288 | case NFCBit.SHM:
289 | drawSHMSignals(n);
290 | nb.getInfo();
291 | break;
292 | default:
293 | drawRotationSignals(n);
294 | nb.getInfo();
295 | break;
296 | }
297 | }
298 | }
299 | pa.noFill();
300 | pa.stroke(0);
301 | for (int i = 0; i < colNum; i++)
302 | pa.line(0, i * pa.height / colNum, pa.width, i * pa.height / colNum);
303 | pa.popStyle();
304 | }
305 |
306 | void showInfo(String s, float x, float y, float fs) {
307 | pa.pushStyle();
308 | pa.textAlign(CENTER, TOP);
309 | pa.fill(0);
310 | pa.textSize(fs);
311 | pa.text(s, x, y);
312 | pa.popStyle();
313 | }
314 |
315 | // Draw a bar graph to visualize the modeArray
316 | // barGraph(float[] data, float x, float y, float width, float height)
317 | void barGraph(float[] data, float _x, float _y, float _w, float _h) {
318 | int colors[] = { pa.color(155, 89, 182), pa.color(63, 195, 128), pa.color(214, 69, 65), pa.color(82, 179, 217),
319 | pa.color(52, 73, 94), pa.color(242, 121, 53), pa.color(0, 121, 53), pa.color(128, 128, 0), pa.color(52, 0, 128),
320 | pa.color(128, 52, 0) };
321 | pa.pushStyle();
322 | pa.noStroke();
323 | float delta = _w / data.length;
324 | for (int p = 0; p < data.length; p++) {
325 | float i = data[p];
326 | int cIndex = (int) i % 10;// min(, colors.length-1);
327 | if (i < 0)
328 | pa.fill(255);
329 | else {
330 | if (i >= 10) {
331 | pa.fill(colors[cIndex]);
332 | } else {
333 | pa.fill(colors[cIndex], 52);
334 | }
335 | }
336 | float h = PApplet.map(0, -1, 0, 0, _h);
337 | pa.rect(_x, _y - h, delta, h);
338 | _x = _x + delta;
339 | }
340 | pa.popStyle();
341 | }
342 |
343 | void barGraph(float[] data, float _x, float _y, float _w, float _h, int ci) {
344 | int colors[] = { pa.color(155, 89, 182), pa.color(63, 195, 128), pa.color(214, 69, 65), pa.color(82, 179, 217),
345 | pa.color(52, 73, 94), pa.color(242, 121, 53), pa.color(0, 121, 53), pa.color(128, 128, 0), pa.color(52, 0, 128),
346 | pa.color(128, 52, 0), pa.color(0) };
347 | pa.pushStyle();
348 | pa.noStroke();
349 | float delta = _w / data.length;
350 | for (int p = 1; p nbitList = getNFCBits();
422 | for (int i = 0; i < nbitList.size(); i++) {
423 | NFCBit nb = nbitList.get(i);
424 | PApplet.print("[", i, "]", nb.getName(), ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
425 | PApplet.print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
426 | PApplet.println("V=", PApplet.nf(nb.getSpeed(), 0, 2), "km/h; f=", PApplet.nf(nb.getFrequency(), 0, 2), "Hz");
427 | }
428 | PApplet.println("===");
429 | }
430 |
431 | public void printLastBit() { //print the latest tag appearance
432 | ArrayList nbitList = getNFCBits();
433 | if (nbitList.size()>0) {
434 | NFCBit nb = nbitList.get(0);
435 | PApplet.print(nb.getName(), ":", nb.getModeString(), "(mode= ", nb.getMode(), ") ");
436 | PApplet.print(nb.getTokenTypeString(), nb.getMotionTypeString(), "|");
437 | PApplet.println("V=", PApplet.nf(nb.getSpeed(), 0, 2), "km/h; f=", PApplet.nf(nb.getFrequency(), 0, 2), "Hz");
438 | }
439 | PApplet.println("===");
440 | }
441 |
442 | // #NFCSense Algorithm
443 |
444 | public void updateNFCBits() {
445 | if (lastIDList.size() > 0) {
446 | int lastID = lastIDList.get(lastIDList.size() - 1);
447 | NFCBit nbit = nbits.get(lastID);
448 | int previousMType = -1;
449 | if (lastIDList.size() > 1)
450 | previousMType = nbits.get(lastIDList.get(lastIDList.size() - 2)).getMotionType();
451 | nbit.getFeatures(previousMType);
452 | }
453 | }
454 |
455 | public ArrayList getNFCBits() {
456 | ArrayList nbList = new ArrayList();
457 | for (int i=lastIDList.size()-1; i>=0; i--) {
458 | nbList.add(nbits.get(lastIDList.get(i)));
459 | }
460 | return nbList;
461 | }
462 |
463 | int searchID(ArrayList id_db, long id) {
464 | int index = -1;
465 | for (int i = 0; i < id_db.size(); i++) {
466 | if (id_db.get(i) == id) {
467 | index = i;
468 | break;
469 | }
470 | }
471 | return index;
472 | }
473 |
474 | long IDtoLong(int[] b) {
475 | return (long) b[0] * 256 * 256 * 256 + (long) b[1] * 256 * 256 + (long) b[2] * 256 + (long) b[3];
476 | }
477 |
478 | String decoder(long l) {
479 | return (l / (256 * 256 * 256)) % 256 + "," + (l / (256 * 256)) % 256 + "," + (l / (256)) % 256 + "," + l % 256;
480 | }
481 |
482 | public void drawMotionModeRecords(float x, float y, float gW, float gH) {
483 | String[] mTypeItems={"LIN", "ROT", "SHM", "CR1", "CR2", "CR3", "CL1", "CL2"};
484 | int colors[] = {
485 | pa.color(155, 89, 182), pa.color(63, 195, 128), pa.color(214, 69, 65),
486 | pa.color(82, 179, 217), pa.color(52, 73, 94), pa.color(242, 121, 53),
487 | pa.color(0, 121, 53), pa.color(128, 128, 0), pa.color(52, 0, 128),
488 | pa.color(128, 52, 0), pa.color(0)
489 | };
490 | for (int n=0; n getIDTable() {
521 | ArrayList ids = new ArrayList();
522 | for(int i = 0; i < lastIDList.size();i++) {
523 | ids.add(decoder(id_db.get(lastIDList.get(i))));
524 | }
525 | return ids;
526 | }
527 |
528 | public ArrayList getNFCBitTable() {
529 | return nbits;
530 | }
531 |
532 | public void setReadRate(float v) {
533 | SAMPLE_RATE = v;
534 | }
535 |
536 | public void setTimer1(float v) {
537 | TTL1_THLD = v;
538 | }
539 |
540 | public void setTimer2(float v) {
541 | TTL2_THLD = v;
542 | }
543 |
544 | public float getReadRate() {
545 | return SAMPLE_RATE;
546 | }
547 |
548 | public float getTimer1() {
549 | return TTL1_THLD;
550 | }
551 |
552 | public float getTimer2() {
553 | return TTL2_THLD;
554 | }
555 |
556 | public void checkTagID() { // called in Serial so that it won't be limited by the 60fps refresh rate
557 | int id_read = searchID(id_db, IDtoLong(rfid));
558 | updateOnTimers(id_read);
559 | updateIntervals(id_read);
560 | updateMTypes(id_read);
561 | lastRead = id_read; // update lastRead after the interval is obtained.
562 | if (id_read >= 0) {
563 | if (id_read != lastIDIndex) {
564 | IDModeString = nbits.get(id_read).getStateStrArray()[0];
565 | for (int i = lastIDList.size() - 1; i >= 0; i--) {
566 | if (id_read == lastIDList.get(i))
567 | lastIDList.remove(i);
568 | }
569 | lastIDList.add(id_read);
570 | lastIDIndex = id_read;
571 | }
572 | }
573 | if (DEBUG_ID)
574 | PApplet.println(rfid[0], rfid[1], rfid[2], rfid[3]);
575 | ++ts; //increase the timestep
576 | }
577 |
578 | void updateOnTimers(int id_read) { // t1, t2, and idOnCounters
579 | // ====ON TIMER BEGIN====//
580 | ttl1 = pa.millis() - last_t1;
581 |
582 | if (id_read >= 0) { // id_read>=0
583 | lastIDString = "[" + rfid[0] + "," + rfid[1] + "," + rfid[2] + "," + rfid[3] + "]";
584 | NFCBit nb = nbits.get(id_read);
585 | if (lastID != id_read) { // edge of different tags
586 | for (int n = modeArray.length - 1; n >= 0; n--)
587 | modeArray[n] = -1;
588 | }
589 | // Calc T_on begin
590 | if (lastRead != id_read) {
591 | nb.reset();
592 | appendArray(modeArray, idNum + id_read);
593 | tOnCounter[id_read] = 1; // for single-tag pattern and orientation
594 | } else { // lastRead == id_read
595 | appendArray(modeArray, id_read);
596 | ++tOnCounter[id_read]; // for single-tag pattern and orientation
597 | }
598 | // Calc T_on end
599 | last_t2 = pa.millis(); // reset t2
600 |
601 | // Calc T_ibi begin
602 | if (lastID != id_read) { // was a different tag
603 | if (ibiCounter[id_read] == 0) { //
604 | if (ibiLastEventTS[id_read] != 0)
605 | lastIBI[id_read] = ts - ibiLastEventTS[id_read];
606 | ibiLastEventTS[id_read] = ts;
607 | ++ibiCounter[id_read];
608 | last_t1 = pa.millis();
609 | profileReady = false;
610 | }
611 | if (lastIDIndex > 0)
612 | nb.t_IBI = ibiLastEventTS[id_read] - ibiLastEventTS[lastIDIndex];
613 | } else { // was the same tag
614 | if (ibiCounter[id_read] == 0) {
615 | if (ibiLastEventTS[id_read] != 0) {
616 | lastIBI[id_read] = ts - ibiLastEventTS[id_read];
617 | ++ibiCounter[id_read];
618 | last_t1 = pa.millis();
619 | profileReady = false;
620 | }
621 | ibiLastEventTS[id_read] = ts;
622 | }
623 | nb.t_I = (int) lastIBI[id_read]; // update tI
624 | }
625 | // Calc T_ibi end
626 | } else { // id_read<0
627 | ttl2 = pa.millis() - last_t2; // start counting t2
628 | if (lastRead >= 0) { // push last t_on
629 | for (int n = 0; n < tOnCounter[lastRead]; n++) {
630 | appendArray(tOnCntrArray[lastRead], tOnCounter[lastRead]); // line graph
631 | }
632 | tOnCounter[lastRead] = 0;
633 | ibiCounter[lastRead] = 0;
634 | last_t1 = pa.millis();
635 | }
636 |
637 | if (ttl1 > TTL1_THLD) {
638 | for (int n = 0; n < idNum; n++) { // reset params
639 | ibiCounter[n] = 0;
640 | lastIBI[n] = 0;
641 | ibiLastEventTS[n] = 0;
642 | }
643 |
644 | if (!profileReady) { // count the modeArray from the back
645 | int ptr = modeArray.length - 1;
646 | if (lastID >= 0) {
647 | NFCBit nb = nbits.get(lastID);
648 | nb.profile.clear();
649 | for (int n = modeArray.length - 1; n >= 0; n--) {
650 | if (modeArray[n] >= idNum) {
651 | int d = ptr - n;
652 | if (d > 0)
653 | nb.profile.add(d);
654 | ptr = n;
655 | }
656 | }
657 | }
658 | profileReady = true;
659 | }
660 |
661 | if (ttl2 > TTL2_THLD) {
662 | if (lastIDIndex >= 0) {
663 | lastIDString = "";
664 | lastIDIndex = -1;
665 | for(int i = 0 ; i TTL1_THLD, ttl2, ttl2 > TTL2_THLD, lastRead, id_read);
681 | // ====ON TIMER END====//
682 | }
683 |
684 | void updateIntervals(int id_read) {
685 | if (id_read >= 0) {
686 | if (lastID != id_read) { // edge of different tags
687 | lastID = id_read;
688 | for (int n = 0; n < idNum; n++) {
689 | if (n == id_read) {
690 | appendArray(idArray[n], idNum + n); // ???lastID != id_read
691 | } else {
692 | appendArray(idArray[n], -1); // not the current id_read.
693 | }
694 | }
695 | appendArray(eventArray, 10 + id_read); //
696 | } else { // lastID == id_read
697 |
698 | for (int n = 0; n < idNum; n++) {
699 | if (n == id_read) {
700 | appendArray(idArray[n], n); // lastID == id_read
701 | } else {
702 | appendArray(idArray[n], -1);
703 | }
704 | }
705 | appendArray(eventArray, id_read);
706 | }
707 | } else {
708 | appendArray(eventArray, -1);
709 | for (int n = 0; n < idNum; n++) {
710 | appendArray(idArray[n], -1); // update idArray
711 | }
712 | }
713 |
714 | for (int n = 0; n < idNum; n++) {
715 | appendArray(idSCntArray[n], (lastIBI[n] > 0 ? 300 / lastIBI[n] : 0));
716 | }
717 | // ====INTERVAL END====//
718 | }
719 |
720 | void updateMTypes(int id_read) {
721 | if (id_read >= 0) {
722 | int m = nbits.get(id_read).getMotionType()-1;
723 | for (int n = 0; n < MotionTypeNum; n++) {
724 | if (n == m) {
725 | appendArray(mTypeArray[n], n); // ???lastID != id_read
726 | } else {
727 | appendArray(mTypeArray[n], -1); // not the current id_read.
728 | }
729 | }
730 | } else {
731 | for (int n = 0; n < MotionTypeNum; n++) {
732 | appendArray(mTypeArray[n], -1);
733 | }
734 | }
735 | // ====INTERVAL END====//
736 | }
737 |
738 | class NFCBitAL extends NFCBit {
739 | final static int NA = 0;
740 | final static int SLIDING = 1;
741 | NFCBitAL(float[] la, String[] sa) {
742 | super(NFCBit.ABOVE_Z_STAR, L_MOTION, la, sa);
743 | mode = SLIDING;
744 | modeStringArray = new String[]{"", "sliding"};
745 | }
746 | void getInfo() {
747 | showInfo(IDModeString, gW/2, 40, tSize);
748 | showInfo("at "+(V>=0? PApplet.nf(V, 0, 2):"---")+" km/hr", gW/2, 40+tSize, 48);
749 | }
750 | void printInfo() {
751 | PApplet.print(IDModeString);
752 | PApplet.println(" @ "+(V>=0? PApplet.nf(V, 0, 2):"---")+" km/hr");
753 | }
754 | void getFeatures(int lastType) {
755 | t_M = 0;
756 | n = profile.size(); //num of segments
757 | for (int i : profile) t_M += i; //the sum of all components (for robustness)
758 | if (n>=1) {
759 | V = (float)(t_M > 0 ? (l_onArray[0] * 0.0036) * SAMPLE_RATE / t_M : 0);
760 | mode = SLIDING;
761 | } else {
762 | V = 0;
763 | mode = NA;
764 | }
765 | m=1;
766 | }
767 | }
768 |
769 | class NFCBitAR extends NFCBit {
770 | final static int SPINNING = 1;
771 | NFCBitAR(float[] la, String[] sa) {
772 | super(NFCBit.ABOVE_Z_STAR, ROTATION, la, sa);
773 | mode = SPINNING;
774 | modeStringArray = new String[]{"", "spinning"};
775 | }
776 | void getInfo() {
777 | showInfo(IDModeString, gW/2, 40, tSize);
778 | showInfo("at "+(f>=0? PApplet.nf(f, 0, 2):"---")+" Hz", gW/2, 40+tSize, 48);
779 | }
780 | void printInfo() {
781 | PApplet.print(IDModeString);
782 | PApplet.println(" @ "+(f>=0? PApplet.nf(f, 0, 2):"---")+" Hz");
783 | }
784 | void getFeatures(int lastType) {
785 | n = profile.size(); //num of segments
786 | f = (t_I>1 ? SAMPLE_RATE / t_I : 0); //tI = self IBI
787 | if(f>0) mode = SPINNING;
788 | else mode = NA;
789 | }
790 | }
791 |
792 | class NFCBitAS extends NFCBit {
793 | final static int SWINGING = 1;
794 | NFCBitAS(float[] la, String[] sa) {
795 | super(NFCBit.ABOVE_Z_STAR, SHM, la, sa);
796 | mode = SWINGING;
797 | modeStringArray = new String[]{"", "swinging"};
798 | }
799 | void getInfo() {
800 | showInfo(IDModeString, gW/2, 40, tSize);
801 | showInfo("at "+(f>=0? PApplet.nf(f, 0, 2):"---")+" Hz", gW/2, 40+tSize, 48);
802 | }
803 | void printInfo() {
804 | PApplet.print(IDModeString);
805 | PApplet.println(" @ "+(f>=0? PApplet.nf(f, 0, 2):"---")+" Hz");
806 | }
807 | void getFeatures(int lastType) {
808 | n = profile.size(); //num of segments
809 | f = (float)((t_I>1 ? SAMPLE_RATE / t_I : 0)/2.);
810 | if(f>0) mode = SWINGING;
811 | else mode = NA;
812 | }
813 | }
814 |
815 | class NFCBitB extends NFCBit {
816 | final static int SLIDING = 1;
817 | final static int HOVERING = 2;
818 | NFCBitB(float[] la, String[] sa) {
819 | super(NFCBit.BELOW_Z_STAR, NFCBit.L_MOTION, la, sa);
820 | modeStringArray = new String[]{"", "sliding", "hovering"};
821 | }
822 | void getInfo() {
823 | showInfo(IDModeString+": "+modeStringArray[mode], gW/2, 40, tSize);
824 | showInfo("at "+(V>=0? PApplet.nf(V, 0, 2):"---")+" km/hr", gW/2, 40+tSize, 48);
825 | }
826 | void printInfo() {
827 | PApplet.print(IDModeString+": "+modeStringArray[mode]);
828 | PApplet.println(" @ "+(V>=0? PApplet.nf(V, 0, 2):"---")+" km/hr");
829 | }
830 | void getFeatures(int lastType) {
831 | n = profile.size(); //num of segments
832 | t_M = 0;
833 | for (int i=0; it_M) {
836 | t_M = t; //major component
837 | m=i+1; //index of major component (start counting from 1)
838 | }
839 | }
840 | if (n>1) {
841 | V = (float)(t_M > 0 ? (l_onArray[0] * 0.0036) * SAMPLE_RATE / t_M : 0);//temporal
842 | mode = SLIDING;
843 | } else if (n==1) {
844 | V = (float)(t_M > 0 ? (l_onArray[1] * 0.0036) * SAMPLE_RATE / t_M : 0);
845 | mode = HOVERING;
846 | } else {
847 | V=0;
848 | mode=NA;
849 | }
850 | }
851 | }
852 |
853 | class NFCBitCL extends NFCBit {
854 | final static int NA = 0;
855 | final static int FORWARD = 1;
856 | final static int BACKWARD = 2;
857 | NFCBitCL(float[] la, String[] sa, int motionType) {
858 | super(NFCBit.ABOVE_Z_STAR, motionType, la, sa);
859 | modeStringArray = new String[]{"", "moving forward", "moving backward"};
860 | }
861 | void getInfo() {
862 | showInfo(IDModeString+": "+modeStringArray[mode], gW/2, 40, tSize);
863 | showInfo("at "+(V>=0? PApplet.nf(V, 0, 2):"---")+" km/hr", gW/2, 40+tSize, 48);
864 | }
865 | void printInfo() {
866 | PApplet.print(IDModeString+": "+modeStringArray[mode]);
867 | PApplet.println(" @ "+(V>=0? PApplet.nf(V, 0, 2):"---")+" km/hr");
868 | }
869 | void getFeatures(int lastType) {
870 | n = profile.size(); //num of segments
871 | m = (n==0?0:1);
872 | V = 0;
873 | switch(motionType) {
874 | case COMPOUND_L1:
875 | if (lastType==COMPOUND_L2) {
876 | V = (float)(t_IBI > 0 ? (l_onArray[0] * 0.0036) * SAMPLE_RATE / t_IBI : 0);
877 | mode = BACKWARD;
878 | }
879 | break;
880 | case COMPOUND_L2:
881 | if (lastType==COMPOUND_L1) {
882 | V = (float)(t_IBI > 0 ? (l_onArray[0] * 0.0036) * SAMPLE_RATE / t_IBI : 0);
883 | mode = FORWARD;
884 | }
885 | break;
886 | }
887 | if (V==0) mode = NA;
888 | }
889 | }
890 |
891 | class NFCBitCR extends NFCBit {
892 | final static int NA = 0;
893 | final static int CW = 1;
894 | final static int CCW = 2;
895 | NFCBitCR(float[] la, String[] sa, int motionType) {
896 | super(NFCBit.ABOVE_Z_STAR, motionType, la, sa);
897 | modeStringArray = new String[]{"", "clockwise spinning", "counterclockwise spinning"};
898 | }
899 | void getInfo() {
900 | showInfo(IDModeString+": "+modeStringArray[mode], gW/2, 40, tSize);
901 | showInfo("at "+(f>=0? PApplet.nf(f, 0, 2):"---")+" Hz", gW/2, 40+tSize, 48);
902 | }
903 | void printInfo() {
904 | PApplet.print(IDModeString+": "+modeStringArray[mode]);
905 | PApplet.println(" @ "+(f>=0? PApplet.nf(f, 0, 2):"---")+" Hz");
906 | }
907 | void getFeatures(int lastType) {
908 | n = profile.size(); //num of segments
909 | m = (n==0?0:1); //major component
910 | f = (t_I>1 ? SAMPLE_RATE / t_I : 0); //t_I:self_IBI
911 | if (f>0) {
912 | switch(motionType) {
913 | case NFCBit.COMPOUND_R1:
914 | if (lastType == NFCBit.COMPOUND_R3) mode=CCW;
915 | if (lastType == NFCBit.COMPOUND_R2) mode=CW;
916 | break;
917 | case NFCBit.COMPOUND_R2:
918 | if (lastType == NFCBit.COMPOUND_R1) mode=CCW;
919 | if (lastType == NFCBit.COMPOUND_R3) mode=CW;
920 | break;
921 | case NFCBit.COMPOUND_R3:
922 | if (lastType == NFCBit.COMPOUND_R2) mode=CCW;
923 | if (lastType == NFCBit.COMPOUND_R1) mode=CW;
924 | break;
925 | }
926 | } else {
927 | mode=NA;
928 | }
929 | }
930 | }
931 |
932 |
933 | class NFCBitT extends NFCBit {
934 | final static int NA = 0;
935 | final static int FORWARD = 1;
936 | final static int BACKWARD = 2;
937 | NFCBitT(float[] la, String[] sa) {
938 | super(NFCBit.ABOVE_THETA_STAR, L_MOTION, la, sa);
939 | modeStringArray = new String[]{"", "moving forward", "moving backward"};
940 | }
941 | void getInfo() {
942 | showInfo(IDModeString+": "+modeStringArray[mode], gW/2, 40, tSize);
943 | showInfo("at "+(V>=0? PApplet.nf(V, 0, 2):"---")+" km/hr", gW/2, 40+tSize, 48);
944 | }
945 | void printInfo() {
946 | PApplet.print(IDModeString+": "+modeStringArray[mode]);
947 | PApplet.println(" @ "+(V>=0? PApplet.nf(V, 0, 2):"---")+" km/hr");
948 | }
949 | void getFeatures(int lastType) {
950 | n = profile.size(); //num of segments
951 | t_M = 0;
952 | for (int i=0; it_M) {
955 | t_M = t; //major component
956 | m=i+1; //index of major component (start counting from 1)
957 | }
958 | }
959 | if (n>1) {
960 | V = (float)(t_M > 0 ? (l_onArray[0] * 0.0036) * SAMPLE_RATE / t_M : 0);
961 | mode=(m>=2 ? FORWARD : BACKWARD);
962 | } else {
963 | V=0;
964 | mode=NA;
965 | }
966 | }
967 | }
968 |
969 |
970 |
971 |
972 | }
973 |
--------------------------------------------------------------------------------