Introduction: IoT Bookmark and Reading (Book Ratings) Tracker W/ Qubitro

About: AI & Full-Stack Developer | @EdgeImpulse | @Particle | Maker | Independent Researcher

Via Nano 33 IoT, use RFID tags as bookmarks to record your ratings. Then, inspect them on Qubitro to grasp and review chapters deliberately.

Supplies

2 x PCBWay Custom PCB

1 x Arduino Nano 33 IoT

1 x MFRC522 RFID Reader

1 x SH1106 OLED Display (128x64)

1 x 5mm Green LED

2 x COM-09032 Analog Joystick

4 x Button (6x6)

1 x Creality CR-6 SE 3D Printer

1 x Power Jack

1 x External Battery

1 x Jumper Wires

Step 1: Story

While reading books or comics, I am fond of recording my ratings on a daily basis to track any surge or plunge in my interest regarding each chapter. Also, I can review books effortlessly by scrutinizing my ratings and notes after completing reading them.

Since I have always logged my ratings on a notebook or a piece of paper, my home library has been deluged with unsolicited paper clusters. Therefore, I decided to create this IoT device to log and monitor my book ratings so as to obviate the need for handwriting.

After perusing book review and classification methods, I decided to employ this device to rate and record six different book characteristics which denote a book's quality and reliability:

  • Plot
  • Delineation
  • Immersion
  • Prolixity
  • Characters
  • Editing

For each characteristic above, I defined four different rating points to create a concise and coherent rating system with the collected data:

  • 1 ➡ Mundane
  • 2 ➡ Interesting
  • 3 ➡ Fascinating
  • 4 ➡ Captivating

After defining my rating system, I decided to utilize RFID disk tags to identify books rather than scanning barcodes (ISBNs) with a barcode scanner since I wanted to design unique bookmarks with the RFID disk tags for each book. Therefore, I connected an MFRC522 RFID reader to the Arduino Nano 33 IoT so as to detect UIDs.

To display the rating settings menu, I connected an SH1106 OLED screen to the Nano 33 IoT. Then, I created a simple controller to adjust ratings for each characteristic with joysticks and buttons.

Instead of developing a web application from scratch to log and monitor the mentioned book ratings transferred by the Nano 33 IoT, I decided to utilize the Qubitro portal to build an IoT application. Since Qubitro supports various connectivity methods with different development boards and provides an easy-to-understand interface to visualize the received data packets on the cloud, I did not encounter any issues while building my IoT application for this project.

After completing wiring on a breadboard and testing the code for transferring data packets to the Qubitro application, I designed Batman-themed base and controller PCBs for this project. When I was watching the Batman: The Animated Series recently, I saw a bat-themed library in the Batcave. Since Batman is my favorite comic book character, I thought it would be interesting to design this device as if it is a part of that library in the Batcave.

Lastly, I also designed a complementary Batman-inspired book stand (3D printable) to insert the base and controller PCBs in order to create a robust and stylish device emphasizing the Batman theme gloriously :)

🎁🎨 Huge thanks to PCBWay for sponsoring this project.

🎁🎨 Also, huge thanks to Creality3D for sponsoring a Creality CR-6 SE 3D Printer.

🎁🎨 If you want to purchase some products from Creality3D, you can use my 10% discount coupon (Aktar10) even for their new and most popular printers: CR-10 Smart, CR-30 3DPrintMill, Ender-3 Pro, and Ender-3 V2. You can also use the coupon for Creality filaments.

Step 2: Designing and Soldering Batman-themed Base and Controller PCBs

Before prototyping my Batman-themed base and controller PCB designs, I tested all connections and wiring with the Arduino Nano 33 IoT and the MFRC522 RFID reader.

Then, I designed the Batman-themed base and controller PCBs by utilizing KiCad - inspired by the legends of the Dark Knight :) I attached the Gerber files for both PCBs below. Therefore, if you want, you can order my PCB designs from PCBWay to create your RFID-enabled IoT bookmark and reading tracker so as to transfer your book ratings effortlessly to a Qubitro application.

Click here to inspect and order the base and controller PCBs directly on PCBWay.

First of all, by utilizing a soldering iron, I attached headers (female), COM-09032 analog joysticks, pushbuttons (6x6), a 5mm green LED, and a power jack to the base and controller PCBs.

📌 Component list on the base PCB:

A1 (Headers for Arduino Nano 33 IoT)

RFID1 (Headers for MFRC522 RFID Reader)

SH1106 (Headers for SH1106 OLED Display)

J1 (Headers for Controller PCB)

D1 (5mm Green LED)

J2 (Power Jack)

📌 Component list on the controller PCB:

J1 (Headers for Base PCB)

U1, U2 (COM-09032 Analog Joystick)

K1, K2, K3, K4 (6x6 Pushbutton)

Step 3: Making Connections and Adjustments

// Connections
// Arduino Nano 33 IoT :  
//                                MFRC522
// D3  --------------------------- RST
// D4  --------------------------- SDA
// D11 --------------------------- MOSI
// D12 --------------------------- MISO
// D13 --------------------------- SCK
//                                SH1106 OLED Display (128x64)
// D6  --------------------------- SDA
// D5  --------------------------- SCK
// D7  --------------------------- RES
// D8  --------------------------- DC
// D9  --------------------------- CS
//                                JoyStick (R)
// A0  --------------------------- VRY
// A1  --------------------------- VRX
// A2  --------------------------- SW
//                                JoyStick (L)
// A3  --------------------------- VRY
// A4  --------------------------- VRX
// A5  --------------------------- SW
//                                Button (Up)
// A6  --------------------------- S
//                                Button (Right)
// A7  --------------------------- S
//                                Button (Left)
// D2  --------------------------- S
//                                Button (Down)
// D10 --------------------------- S
//                                5mm Green LED
// D0  --------------------------- +

After completing soldering, I attached all remaining components to the Batman-themed base and controller PCBs via headers - Arduino Nano 33 IoT, MFRC522 RFID reader, and SH1106 OLED screen.

Then, I connected the base PCB to the controller PCB by utilizing male jumper wires.

Step 4: Designing and Printing a Batman-inspired Book Stand

Since I wanted to apply the bat theme to create a device as if it is a part of the Batcave from the animated series, I decided to design a complementing book stand to display the books I am currently reading in my home library. To insert and attach the Batman-themed base and controller PCBs to the book stand effortlessly, I added slots and hooks. Also, I inscribed the prominent bat symbol on the book stand to emphasize the Batman theme gloriously :)

I designed the book stand in Autodesk Fusion 360. You can download its STL file below.

Then, I sliced my book stand 3D model (STL file) in Ultimaker Cura.

Since I wanted to create a solid structure for the book stand and complement the Batman theme, I utilized this PLA filament:

  • Black

Finally, I printed the book stand (model) with my Creality CR-6 SE 3D Printer. Although I am a novice in 3D printing, and it is my first FDM 3D printer, I got incredible results effortlessly with the CR-6 SE :)

Step 5: Assembling the Book Stand and Creating RFID Bookmarks

After printing my book stand 3D model, I affixed the Batman-themed base and controller PCBs to the book stand. I placed the controller PCB via the hooks on the front. Then, I fastened the base PCB to its slot on the top via a hot glue gun and utilized a cable tie to make a rigid and stable connection.

Since I decided to employ RFID disk tags to create unique bookmarks in order to identify books, I fastened the disk tags to my limited edition comic bookmarks I purchased from a comic book convention in my hometown.

Step 6: Setting Up an IoT Application on Qubitro

To log and monitor the book ratings transferred by the Nano 33 IoT, I decided to utilize the Qubitro portal to build an IoT application. Qubitro provides developer-friendly features and supports various connectivity methods such as a fully-featured MQTT broker and The Things Stack devices. Since Qubitro has easy-to-understand online examples with technical guides and allows the user to visualize the received data packets on the cloud with specialized widgets effortlessly, I highly recommend building IoT applications with Qubitro.

#️⃣ First of all, go to the Qubitro portal and sign in.

#️⃣ Then, create a new project (IoT application) and define its name and description.

#️⃣ To create a new Qubitro device under the application, choose a connectivity method depending on your project's requirements. Select the MQTT option to transfer data via the Qubitro MQTT broker to the given Qubitro device.

#️⃣ Define the device information and details.

If required, you can also use the application's MQTT credentials to publish data via the Qubitro APIs.

#️⃣ After creating the Qubitro device successfully, open the device on the project dashboard and click Settings.

#️⃣ Then, copy the device ID and token to transfer data packets from the Nano 33 IoT to the Qubitro device via the MQTT broker.

Step 7: Analyzing the Collected Data on Qubitro

After building my IoT application on Qubitro, I started to send data packets (book ratings) from the Nano 33 IoT to the Qubitro device under the application via the MQTT broker immediately.

To analyze the collected data, I utilized the built-in chart feature in the device interface.

You can inspect the code for transferring book ratings via the Qubitro MQTT broker in Step 4.

#️⃣ After the Qubitro device receives data packets, open the device on the project dashboard and click Analytics.

#️⃣ Then, create a chart with unique colors for each data element to scrutinize the collected data in a given period.

Step 8: Creating Widgets to Visualize the Collected Data on Qubitro

#️⃣ First of all, on the project dashboard, go to Monitoring so as to create a new monitoring dashboard.

#️⃣ Then, click the Add widget button.

#️⃣ Define the required information for the widget: title, project (IoT application) name, device name, and widget type (e.g., area chart).

#️⃣ To customize the recently created widget, assign a data element (sensor value), select the widget color, and adjust the appearance settings.

After creating widgets for each data element, the Qubitro portal should show a monitoring dashboard as follows.

Step 9: Programming the Arduino Nano 33 IoT

First of all, I needed to install the SAMD21 core to set up the Arduino Nano 33 IoT on the Arduino IDE.

#️⃣ On the Arduino IDE, navigate to Tools > Board > Boards Manager.

#️⃣ Then, search for the Arduino SAMD Boards (32-bits ARM Cortex-M0+) core and install it.

#️⃣ Go to Tools > Board > Arduino SAMD Boards (32-bits ARM Cortex-M0+) in order to select the Arduino Nano 33 IoT.

#️⃣ After setting up the Nano 33 IoT successfully, download the required libraries to transfer data packets via the Qubitro MQTT broker:

WiFiNINA | Download

mqtt-client-arduino | Download

#️⃣ Then, download the required libraries for the MFRC522 RFID reader and the SH1106 OLED screen:

rfid | Download

Adafruit_SH110x | Download

Adafruit-GFX-Library | Download

⭐ Include the required libraries.

#include <QubitroMqttClient.h>
#include <WiFiNINA.h> 
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <MFRC522.h>

⭐ Initiate the Wi-Fi and Qubitro MQTT clients.

⭐ Define the Wi-Fi settings.

⭐ Define the Qubitro device settings and information (ID and token).

WiFiClient wifiClient;
QubitroMqttClient mqttClient(wifiClient);

// Define the Wi-Fi settings.
char ssid[] = "<_SSID_>";   
char pass[] = "<_PASSWORD_>";

// Define the Qubitro device settings and information.
char deviceID[] = "<_DEVICE_ID_>";
char deviceToken[] = "<_DEVICE_TOKEN_>";
char host[] = "broker.qubitro.com";
int port = 1883;

⭐ Define the SH1106 OLED screen settings.

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_MOSI     6
#define OLED_CLK      5
#define OLED_DC       8
#define OLED_CS       9
#define OLED_RST      7

// Create the SH1106 OLED screen.
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RST, OLED_CS);

⭐ Create the MFRC522 instance and define the MFRC522 module key input.

#define RST_PIN   3
#define SS_PIN    4
MFRC522 mfrc522(SS_PIN, RST_PIN);

// Define the MFRC522 module key input.
MFRC522::MIFARE_Key key;

⭐ Initialize the SH1106 OLED screen.

  display.begin(0, true);
  display.display();
  delay(1000);

  display.clearDisplay();   
  display.setTextSize(2); 
  display.setTextColor(SH110X_BLACK, SH110X_WHITE);
  display.setCursor(0,0);
  display.println("IoT");
  display.println("Bookmark");
  display.display();
  delay(1000);

⭐ Connect to the given Wi-Fi network.

  Serial.println("Connecting to the Wi-Fi network...");
  while(WiFi.begin(ssid, pass) != WL_CONNECTED){
    Serial.print(".");
    delay(1000);
  }
  Serial.println("Connected to the Wi-Fi network!");

⭐ Set the Qubitro device ID and token for authentication.

⭐ Connect to the Qubitro device via the Qubitro MQTT broker.

  mqttClient.setId(deviceID); 
  mqttClient.setDeviceIdToken(deviceID, deviceToken);
  Serial.println("Connecting to the Qubitro device...");

  // Connect to the Qubitro device via the Qubitro MQTT broker.
  if(!mqttClient.connect(host, port)){
    Serial.println("Qubitro: Connection failed! Error code => ");
    Serial.println(mqttClient.connectError());
    while(1);
  }
  Serial.println("Connected to the Qubitro device!"); 

⭐ Activate the two-way communication with the Qubitro device to get informed of the server responses (received messages).

  mqttClient.onMessage(receivedMessage);                                       
  mqttClient.subscribe(deviceID);

⭐ Initialize the MFRC522 RFID reader (hardware).

  SPI.begin();          
  mfrc522.PCD_Init();
  Serial.println("\n----------------------------------\nApproximate a New Card or Key Tag : \n----------------------------------\n");

⭐ In the read_UID function, detect a new RFID card or tag UID.

⭐ Then, copy the detected UID to the lastRead string, process the lastRead string, and print it on the serial monitor.

int read_UID() {
  // Detect the new card or tag UID. 
  if ( ! mfrc522.PICC_IsNewCardPresent()) { 
    return 0;
  }
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return 0;
  }

  // Display the detected UID on the serial monitor.
  Serial.print("\n----------------------------------\nNew Card or Key Tag UID : ");
  for (int i = 0; i < mfrc522.uid.size; i++) {
    lastRead += mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ";
    lastRead += String(mfrc522.uid.uidByte[i], HEX);
  }
  lastRead.trim();
  lastRead.toUpperCase();
  Serial.print(lastRead);
  Serial.print("\n----------------------------------\n\n");
  mfrc522.PICC_HaltA();
  return 1;
}

⭐ Maintain the MQTT connection with the Qubitro broker.

mqttClient.poll(); 

⭐ If an RFID card or tag UID is detected and stored, initiate the rating settings menu:

⭐ Display the detected UID and the current book ratings on the SH1106 OLED screen.

⭐ Then, adjust book ratings by utilizing joystick (first and second) movements and control buttons (up, right, left, and down).

⭐ If the second joystick's switch is pressed, create a string in the JSON format to transfer the detected UID and the adjusted book ratings to the Qubitro device:

  • UID
  • plot
  • delineation
  • immersion
  • prolixity
  • characters
  • editing

⭐ Then, send the given data packet to the Qubitro device via the Qubitro MQTT broker.

⭐ Finally, return to the home screen and clear the lastRead string (detected UID).

⭐ If the first joystick's switch is pressed, return to the home screen and clear the lastRead string (detected UID) without sending the data packet.

  if(lastRead != ""){
    uid_activated = true; 
    // If an RFID card or tag is detected, open the rating settings menu.
    while(uid_activated){
      read_controls();
      mqttClient.poll(); 
      display.clearDisplay();
      display.setTextSize(1);
      display.setTextColor(SH110X_WHITE);
      display.setCursor(0,5);
      display.print("UID: "); display.println(lastRead);
      display.print("Plot :        "); display.println(options[0]);
      display.print("Delineation : "); display.println(options[1]);
      display.print("Immersion :   "); display.println(options[2]);
      display.print("Prolixity :   "); display.println(options[3]);
      display.print("Characters :  "); display.println(options[4]);
      display.print("Editing :     "); display.println(options[5]);
      display.display();
      delay(150);
      // Adjust book ratings by utilizing joysticks and control buttons:
      if(joystick_x_1 >= 850){ if(!up) options[0] = 1; if(!right) options[0] = 2; if(!left) options[0] = 3; if(!down) options[0] = 4; }
      if(joystick_x_1 <= 150){ if(!up) options[1] = 1; if(!right) options[1] = 2; if(!left) options[1] = 3; if(!down) options[1] = 4; }
      if(joystick_y_1 >= 850){ if(!up) options[2] = 1; if(!right) options[2] = 2; if(!left) options[2] = 3; if(!down) options[2] = 4; }
      if(joystick_x_2 >= 850){ if(!up) options[3] = 1; if(!right) options[3] = 2; if(!left) options[3] = 3; if(!down) options[3] = 4; }
      if(joystick_x_2 <= 150){ if(!up) options[4] = 1; if(!right) options[4] = 2; if(!left) options[4] = 3; if(!down) options[4] = 4; }
      if(joystick_y_2 >= 850){ if(!up) options[5] = 1; if(!right) options[5] = 2; if(!left) options[5] = 3; if(!down) options[5] = 4; }
      // Send the given book ratings to the Qubitro device via the Qubitro MQTT broker.
      if(!joystick_sw_2){
       digitalWrite(control_led, HIGH);
       mqttClient.beginMessage(deviceID);   
       // Create a string in the JSON format to transfer data to the Qubitro device successfully.
       mqttClient.print("{\"UID\":\"" + lastRead + "\",\"plot\":" + String(options[0]) + ",\"delineation\":" + String(options[1]) + ",\"immersion\":" + String(options[2]) + ",\"prolixity\":" + String(options[3]) + ",\"characters\":" + String(options[4]) + ",\"editing\":" + String(options[5]) + "}");
       mqttClient.endMessage();             
       delay(3000); 
       Serial.println("Message Sent!");
       // Exit and clear:
       lastRead = "";
       display.clearDisplay();   
       display.setTextSize(2); 
       display.setTextColor(SH110X_BLACK, SH110X_WHITE);
       display.setCursor(0,0);
       display.println("IoT");
       display.println("Bookmark");
       display.display();
       digitalWrite(control_led, LOW);
       uid_activated = false;
      }

      // Exit and clear:
      if(!joystick_sw_1){
          lastRead = "";
          display.clearDisplay();   
          display.setTextSize(2); 
          display.setTextColor(SH110X_BLACK, SH110X_WHITE);
          display.setCursor(0,0);
          display.println("IoT");
          display.println("Bookmark");
          display.display();
          uid_activated = false;
      }
    }
  }

Step 10: Modes and Features

🦇📗 First of all, the device attempts to connect to the given Wi-Fi network and the Qubitro device via the Qubitro MQTT broker.

🦇📗 Then, the device displays the home screen.

🦇📗 If the device detects an RFID card or tag UID, it initiates the rating settings menu and shows the detected UID and the current book ratings:

  • UID
  • Plot
  • Delineation
  • Immersion
  • Prolixity
  • Characters
  • Editing

🦇📗 On the rating settings menu, the device allows the user to adjust the book ratings by utilizing joystick movements and control buttons:

🕹️ To adjust the Plot rating:

  • Move the first joystick to the right ➡ Press any control button

🕹️ To adjust the Delineation rating:

  • Move the first joystick to the left ➡ Press any control button

🕹️ To adjust the Immersion rating:

  • Move the first joystick to the up ➡ Press any control button

🕹️ To adjust the Prolixity rating:

  • Move the second joystick to the right ➡ Press any control button

🕹️ To adjust the Characters rating:

  • Move the second joystick to the left ➡ Press any control button

🕹️ To adjust the Editing rating:

  • Move the second joystick to the up ➡ Press any control button

🎮 Rating points by control buttons:

  • Up button ➡ Mundane [1]
  • Right button ➡ Interesting [2]
  • Left button ➡ Fascinating [3]
  • Down button ➡ Captivating [4]

🦇📗 If the second joystick's switch is pressed, the device sends the data packet (the detected UID and the adjusted book ratings) to the Qubitro device via the Qubitro MQTT broker.

🦇📗 Then, the device blinks the 5mm green LED if the Qubitro device receives the transferred data packet successfully.

🦇📗 After sending the data packet, the device returns to the home screen.

🦇📗 If the first joystick's switch is pressed, the device also returns to the home screen without transferring the data packet.

🦇📗 The device stores the adjusted book ratings and shows them on the rating settings menu when being activated so as to remind the user of the previously assigned book ratings.

🦇📗 If the Nano 33 IoT throws an error while operating, the device prints the error code and details on the serial monitor.

🦇📗 Also, the device prints notifications and UID readings on the serial monitor for debugging.

🦇📗 After transferring data packets to the Qubitro device, the Qubitro portal lets the user visualize the book ratings on the monitoring dashboard, as explained in Step 3.2.

Step 11: Videos and Conclusion

As far as my experiments go, the device works impeccably while adjusting the book ratings and transferring data packets to the Qubitro device via the Qubitro MQTT broker :)

Step 12: Schematics

Step 13: Code and Downloads