Skip to content

User Manual

Product description

The product is a RFID scanner used for time registration. It is meant to be a way for employees to check in- and out.

Step-by-step guide

An introduction to your product, start by giving context about the assignment and what you have worked on, your idea’s, …, like a summary in a research paper.

Introduction

Welcome to the product manual of the Time Registration blueprint. This blueprint is part of a course I took at the HvA. The idea is that through the use of sensors make a device that employees can use to check in and out. With the data you receive you build a database where you can show the check in/out times on a neat little website. Below this paragraph you will see an image of the product. The design is meant to look like a company building.

Product imageCheck in and out system

Step 1 Arduino & Docker

  1. Download Arduino IDE for your specific device and follow the instructions on the website.
  2. After installing Arduino, you will need to install these libraries: MFRC522 and ArduinoJson.

  3. Then we have to download the docker to run the back-end on. My course gave me the docker files, they can be found here: https://gitlab.fdmci.hva.nl/IoT/individual-project/code/individual-project-docker

  4. After downloading the files open your terminal, enter the following command:

docker -v

The result should be a docker version.

In the command line navigate to the place you downloaded the docker documents. Do this by typing the following line in the terminal:

cd “

Then start the docker program by typing this line in the terminal:

docker-compose up

Open up the docker, you should now see 5 files. Well done! :D

Tip: Test if it works by opening chrome and typing localhost.

Step 2 Solderen

The next step for preperation is to solder our Wemos D1 Mini and LED.

Wemos For the Wemos there is a handy tutorial that you can follow that explains the steps and shows you how to do it Soldering the headers on a Wemos D1 Mini

LED For the LED display you can follow this video from the Tech Vegan. How to Solder 16x2 LCD Display Properly\

Step 3 Avengers, assemble your breadboard

Wiring

This is the wiring diagram with all three of the sensors connected.

I would advice to seperate the colours for different power supply types. I used orange for 5v and red for 3v3. It is to prevent confusion and cause magical black smoke to appear.

Step 4 The code and how to use it

Wifi

Setting up the wifi for your WeMos is an important step. Without it, setting up an online dashboard is gonna be a bit tougher.

First thing you need are the correct clients:

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

After that, enter this in the void setup:

Serial.begin(115200);    // Initialize serial communications
  WiFi.begin("SSID", "Password"); //SSID and password

  Serial.print("starting setup");

//    Keep in while-loop while the device is not connected to your accesspoint.
    while (WiFi.status() != WL_CONNECTED) {
       Serial.println("Waiting for connection status=" + String(WiFi.status()));
       delay(1000); // Waiting on connection...
    }
       Serial.println("Connected! status=" + String(WiFi.status())); // tells you the connection status, 3 is connected.

And this is what you put in the void loop:

  WiFiClient client;
  HTTPClient httpClient;

  httpClient.begin(client, "http://koffiepunthva.nl/api");
  int httpCode = httpClient.GET();

  if(httpCode == HTTP_CODE_OK) { // HTTP_CODE_OK == 200
    String payload = httpClient.getString();
    Serial.println(payload);
  } else {
    Serial.println("Unable to connect :(");
  }

  delay(5000);

And after setting up yout wifi, you can continue to work on the rest of your sensors.

LCD

For the LCD 16x2 I used the following code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
    // initialize the LCD
    lcd.begin();

   // Turn on the blacklight and print a message.
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("Hello, world!");

    Serial.begin(115200);
    Serial.println("test");

}

void loop()
{
    // Do nothing here...
}

RFID

//RFID scanner
#include <MFRC522.h>
#include <ArduinoJson.h>

// define
#define RST_PIN D0 // RST-PIN for RC522 - RFID - SPI - Modul GPIO15 
#define SS_PIN  D8  // SDA-PIN for RC522 - RFID - SPI - Modul GPIO2

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance



void setup() {
  SPI.begin();           // Init SPI bus
  mfrc522.PCD_Init();    // Init MFRC522

}

// Helper routine to dump a byte array as hex values to Serial
void dump_byte_array(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

String get_byte_array (byte *buffer, byte bufferSize) {
  String UID = "";
  for (byte i = 0; i < bufferSize; i++) {
    buffer[i] < 0x10 ? " 0" : " ";
    char myHex[10] = "";
    ltoa(buffer[i], myHex, 16); //convert to c string base 16
    UID += String(myHex);
    UID += " ";
  }
  UID.toUpperCase();
  return UID;

}


void loop() {

  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    delay(50);
    return;
  }

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    delay(50);
    return;
  }

  // Show some details of the PICC (that is: the tag/card)
  Serial.print("Card UID:");
  Serial.println(get_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size));
  Serial.println();

  delay(1000);
}

LDR

This is the code for de LDR that I am using.

#define LDRpin A0 // pin where we connected the LDR and the resistor

int LDRValue = 0;     // result of reading the analog pin

void setup() {
  Serial.begin(9600); // sets serial port for communication
}

void loop() {
  LDRValue = analogRead(LDRpin); // read the value from the LDR
  Serial.println(LDRValue);      // print the value to the serial port
  delay(1500);                    // wait a little, this was originally 100, but I put it to 1500 so my serial monitor would not be overloaded with small data.
}

Front end

Now we have reached the part where we can show our data on the website. This is the output of the data so it is important it is easy to read for the public. The front-end consists of three documents, HTML, CSS and JavaScript.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Blueprint dashboard</title>
    <script src="/static/js/app.js" defer></script>
</head>

<body class="dash">

    <header>
        <section>
            <h1>Dashboard Time Registration</h1>
        </section>
    </header>


    <section id="table">
        <table>
            <thead>
                <tr>
                    <td>Naam</td>
                    <td>Card id</td>
                    <td>Tijd</td>
                </tr>
            </thead>
            <tbody></tbody>
        </table>
    </section>
</body>

</html>
The code itself is quite simple. I put an id on the section to be able to style the table better and as a whole at once. You will see the styling next.

/* All */
*,
*::after,
*::before {
    box-sizing: border-box;
}

* {
    margin: 0;
    padding: 0;
}

html {
    width: 100%;
    height: 100vh;
}

body {
    font-family: 'Open sans', sans-serif;
    height: 100vh;
}


/* Index*/
body section#dashboard-button {
    position: fixed;
    top: 60%;
    left: 40%;
}

body section#dashboard-button button {
    background-color: #6970db;
    /* purple */
    border: none;
    color: white;
    padding: 15px 32px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
    border-radius: 10px;
}



/* Dashboard */
body.dash header{
    position: sticky; /* zo blijft hij op zn plek tijdens het scrollen*/
    width: 100%; /* lekker de volle breedte*/
    top: 0; 
    background-color: white;
    height: 100px;
}


body.dash header section {
    height: 100%;
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
}

body.dash header section h1 {
    color: #6970db;
    padding: 10px 5px;
}

body.dash section#table{
    display: flex;
    justify-content: center;
}

.dash td {
    border: 1px solid #ddd;
    padding: 8px;
}

.dash thead{
    padding-top: 12px;
    padding-bottom: 12px;
    text-align: left;
    background-color: #04AA6D;
    color: white;
}
The css is split in three ways; all, index and dashboard. The most important part of the code now is the dashboard code. This is where i styled the table. It is very simplistic, but it is readable and that is the most important goal of css.

// Inez, Open source, goal is to fetch the data, respond in json, made a table and display the table in html code.

const table = document.querySelector('table')

function fetchData(){
    return fetch('http://localhost/getdb.php')
    .then((response) => response.json())
}

async function tableCreate(){
    let html = '';
    const data = await fetchData();
    console.log(data);
    data.forEach(registratie => {
        html += `
        <tr>
            <td>${registratie.naam}</td>
            <td>${registratie.card_id}</td>
            <td>${registratie.datum}</td>
        </tr>
        `;
    });
    table.innerHTML = html;
}

// window.addEventListener()
tableCreate();
The element “querySelector()” returns the first Element within the html document that matches the specified selector. Then it creates a table for and puts in all the selected data from the back-end (which we will get to next) and then it displays the table as inner html and it will show the data to you on your web page.

front end website

I am by no means a Css wizard, but I managed to create a simple and clean looking table.

PHPadmin

If you want a database to save your data you will need to set one up. You will need a servername, username, password and dbname. I used the one that my school provided for me.

The first thing I did was design my database in mySQLWorkbench. It looks like this. If you are following this project I would advice to do the same as I did. It is important to have a link between your databases so if you want to connect them you can.

mySQLOverview of the database design

After importing it in phpmyadmin it should look like this.

PHP tabel schemaOverview of how the tables will be and function

API Documentation

The API is made through your own data and names. In the PHPadmin you fill in the data in the graph like shown and then if you use the servername, username and dbname you can use the data anywhere.

Back end/PHP

The back-end of the website is where the magic happens. There are three-ish pages that make up the back-end of the website. Two are php pages that handle the data, the other one is the javascript (that you saw in front-end) and that connect the php data to the html. You can see javascript as the bridge between the two files.

The first file is insert.php.

Insert.php

<?php
// Inez, Open source, goal is to get data to and from phpmyadmin.
$servername = "mariadb";
$username = "root";
$password = "7YKyE8R2AhKzswfN";
$dbname = "iot";

$cardUID = $_GET["cardUID"];

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

$sql = "INSERT INTO Registratie(card_id,datum) VALUES ('" . $cardUID . "', NOW())";

if ($conn->query($sql) === TRUE) {
  echo "New record created successfully";
} else {
  echo "Error: " . $sql . "<br>" . $conn->error;
}

echo "Hello! $cardUID is here";

It starts off by making a connection to myphpadmin. After that, it inserts the data to the card_id and datum columns in the database that I have in phpmydamin. Instead of using the arduino to give me the time I used the “Now” so the webbrowser gives me the time and it is less code in my arduino.

You can test if the connection works by filling in:

http://localhost/insert.php?cardUID=8D20FFG08A2S05A

(or one of your own card id’s)

The second part of the php code is getting the data from phpmyadmin and getting it back to php.

//getting data from php and putting it in html
$db= $conn;
$tableName="Registratie";
$columns= ['datum', 'card_id'];
$fetchData = fetch_data($db, $tableName, $columns);

function fetch_data($db, $tableName, $columns){
  if(empty($db)){
   $msg= "Database connection error";
  }elseif (empty($columns) || !is_array($columns)) {
   $msg="columns Name must be defined in an indexed array";
  }elseif(empty($tableName)){
    $msg= "Table Name is empty";}
  };

$conn->close();
?>

getdb.php

This document is going to get the data from phpmyadmin and print it in the console so that the javascript can put it into html.

<?php
// Inez, Open source, goal is to put all data from phpmyadmin in to an array and print it in the console.
$servername = "mariadb";
$username = "root";
$password = "7YKyE8R2AhKzswfN";
$dbname = "iot";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}


$sql = "SELECT * FROM `Registratie` INNER JOIN `Gebruiker`ON Registratie.card_id = Gebruiker.card_id ";

$result = $conn->query($sql);

$data[] = array();
//$datum[] = array();
//$card_id[] = array();z
$counter = 0;

if ($result->num_rows > 0) {

    // output data of each row
    while($row = $result->fetch_assoc()) {

        //echo $row["datum"] . " " . $row["card_id"];
        //  $data[] = $row;
        // $card_id[] = $row["card_id"];
        // $datum[] = $row["datum"];
        $data[$counter]["datum"] = $row["datum"];
        $data[$counter]["card_id"] = $row["card_id"];
        $data[$counter]["naam"] = $row["naam"];
        $counter++;
    }

} else {
    echo "0 results";
}

$conn->close();


print_r(json_encode($data));

?>

Step 5 Bob the builder, buildt your case

Making the box

So before we can even start to make the box we have to think what we want it to look like. So I used makerscase.com and Adobe Illustrator to make a cut out drawing of my box.

Digital Design

These are the specifics: (all outside dimensions) - Width: 120.12mm - Height: 126mm - Depth: 92,07mm

  • Material thickness: 3mm (but is personal choice)
  • Closed box
  • Number of bends: 4
  • Bend radius: 35mm
  • Finger size: highest possible
  • Cut line width: 0.25mm

This drawing has boxes for the sensors and the LCD 16x2 screen.

The material I used was a fibre wood plank around 4mm in thickness. I wanted a sturdy box as it is supposed to be outside and should be able to withstand some weather or a lot of use inside the office.

Cut the box

I used the laser cutter at the Makers Lab at the TTH. I used a 4mm fibre wood plank. The printing took about 20 minutes, at 75% speed of cutting and 80% on scanning. The program I used had pre-set settings and I used those. Do remember, if you have more than 35mm bend radius, it might take longer, all those bends have to be individually cut.

Taking everything into account (setting up, framing it right, weighing down the wood and preparing everything) it took me about an hour and a half.

In the program I used the pre-set setting for my type of wood.

Finish the box

Digital DesignFirst prototype design

Due to not having a lot of time this is my first prototype, ~~without the room for the sensors.~~

Extra

There were some things that I was not able to fix.

Failure

The first thing was that I could not get a wifi manager to work, or let the wifi work at school. Not even with a hot spot from my phone. It would only work from home with my own wifi.

Failure

The second thing that did not want to work was the data sending from my wemos to the back-end. This is probably a combination of wifi and the firewall.

Though not everything went according to plan, I did put my energy to good use. What I was good at I put more work in, for example the UI and the physical design part.


Last update: November 6, 2022