This is only a preview of the February 2023 issue of Practical Electronics. You can view 0 of the 72 pages in the full issue. Articles in this series:
|
Make it with Micromite
Phil Boyce – hands on with the mighty PIC-powered, BASIC microcontroller
Part 44: A PicoMite Fingerprint Reader – Part 2
A
couple of months ago we
explored Part 1 of an exciting
biometric project: a PicoMite
Fingerprint Reader. If you followed the
article (Make it with Micromite, Part
42, December 2022), then hopefully
you were successful in connecting and
communicating with the low-cost R503
fingerprint module. However, due to a
few unforeseen issues, the progress of
this project was delayed, and hence last
month we were unable to go to print with
Part 2. Admittedly, I was the cause of the
first issue, in that I got a bit too carried
away with the output voltage on my PSU.
This resulted in the R503 intermittently
sending random data values (on its serial
Tx pin) to the PicoMite – yes, I had
inadvertently destroyed the module.
A replacement R503 was quickly ordered
and arrived in good time. However, this
replacement module also started behaving
strangely (even though I was now using a
dedicated 5V USB PSU). Doubtless, you
have all found that it can be extremely
difficult to track down the cause of random
behaviour in an electronics project. Indeed,
I lost many hours carefully checking wiring
(albeit only six connections) and checking
the program code for what I then assumed
must contain one, or more, bugs. Matters
were not made any easier by the poorly
written (not to mention, incomplete)
datasheet for the R503 fingerprint module.
Eventually, I made the decision to order
yet another replacement R503; in fact, two
replacements were ordered. However, the
recent postal strikes impacted the delivery
of these units – what else could possibly
go wrong! Well, the good news is that the
replacement parts did arrive, so now we
can continue our project. But before we do,
there is one word of caution that I really
wish to emphasise: please be careful not
to bend or stress any of the six thin wires
that protrude from the rear of the R503 –
you have been warned!
Due to the units having only recently
arrived, we will now be extending this
project to three parts. This month, we will
cover the topics of fingerprint enrolment,
and fingerprint searching, so that you
understand what commands need to be
sent to the R503 to perform these tasks,
and in turn, how to interpret the responses
back to the PicoMite. Then, in Part 3, we
will assemble a unit with a built-in display
to act as a standalone fingerprint reader.
Recap
made simple thanks to MMBASIC’s ability
to easily send and receive serial data. In
Part 1 we looked at the structure of any
message that is sent to (or returned from)
the fingerprint module; and this is once
again summarised in Fig.3.
To demonstrate communications between
the PicoMite and the R503 (and to also
check correct connection), we provided
a demonstration program in Part 1 for
download (FP_MessageDemo1.txt). When
the program was RUN, it simply turned
on the blue ring-LED surrounding the
fingerprint sensor – nothing too exciting, but
it confirmed that the hardware was working
and that the PicoMite could successfully
communicate with the R503.
FP_MessageDemo2
We will begin this month by using an
updated version of the FP_MessageDemo1
program. This allows us to better
demonstrate the steps involved in
enrolment, and searching. Download the
aptly named file FP_MessageDemo2.txt
from the February 2023 page of the PE
website (https://bit.ly/pe-downloads) and
install the program into the PicoMite.
When you RUN the program, you should
see the blue ring-LED light up (assuming
The R503 fingerprint module that we are
using is inexpensive (£20), can operate from
just 3.3V and uses a serial UART connection
to communicate with the outside world.
Internally, it deals with all the complex
algorithms that capture and then convert
an image of a fingerprint into a digital
template (which is essentially a long list
of data values). This module is perfect
for linking to a PicoMite so that we can
assemble a complete fingerprint reader.
The circuit diagram from Part 1 is reshown
here in Fig.1. Assembly is made easier if
you use a Pico Expander board, and six
appropriate DuPont
leads (see Fig.2).
Red
3V3
3V3
However, to make
Black
GND
0V
the
R503 do anything
Yellow
Tx
GP1
useful,
commands
Green
Rx
GP0
need
to
be
sent from
Bue
Finger detect
GP2
the PicoMite to the
White
Induction power
3V3
R503 in a certain
order (and observing
Fig.1. All six wires coming from the back of the R503 fingerprint s o m e s p e c i f i c
module need to be connected to the PicoMite as shown above. timings). This is all
Fig.2. Using a Pico Expander board
like the one shown here (along with six
appropriate DuPont leads) makes it
very easy to attach the R503 fingerprint
module to the PicoMite.
50
Practical Electronics | February | 2023
byte, RxPacket(1), which represents the
Confirmation Code, as referred to in the R503
datasheet. For the AuraLEDConfig command
PACKAGE DATA [PD_Qty] CHECKSUM [2]
HEADER [2] ADDRESS [4] IDENTIFIER [1]
LENGTH [2]
3 4 5 6
7
8 9
PD(1)
PD(PD_Qty)
10 11
MFB(x) 1 2
shown in Fig.4, there is just a single Packet
Data byte, and a value of zero means that the
command sent to the R503 was successfully
EF 01
FF FF FF FF
01 Command
dealt with (in this case, the blue LED is on).
(Fixed)
(Default)
02 Data
Other values indicate the command sent to
07 Acknowledge
the R503 was not successful in some way,
08 End of data
and for convenience, a description will be
shown to the right of the byte value. All
Sum of byte values =
Checksum value
possible Confirmation Code values (and their
meaning) are shown in the R503 datasheet;
Fig.3. The structure of the message contains six elements, as shown here. See Part 1
and in our program code, they are stored in
(December 2022) for details as to how the contents are calculated and interpreted.
the array RxACK$() (see lines 30-53).
Note that all byte values are shown as a hexadecimal number.
After the last RxPacket() has been
received, just two more bytes are received, RxMFB(10you have an R503 correctly connected) giving the same result as when
11). These represent the Checksum value (see Fig.3)
you ran the demo from Part 1. However, when you take a closer look at
and if correct, you’ll see a VALID RESPONSE message
the terminal screen you will see all the individual command bytes (in hex)
appear. Essentially, this means the data bytes received are
sent to the R503, and also the bytes sent in response back to the PicoMite.
not corrupted in any way. If for any reason the data was
Fig.4 shows a screenshot of this communication, and if you refer to
corrupted (eg, a loose wire), then the message ERROR:
Part 1, you will see these exact same hex values in the text (on page 61).
Response INVALID will be shown.
The five Package Data bytes highlighted in the COMMAND section – ie,
TxPD(1-5) – represent the AuraLEDConfig command (&h35), along
with the four parameters that determines how the LED should behave.
How to use FP_MessageDemo2
Note that for a Command Message, the byte value of TxPD(1) will always
If you take look at the program listing for FP_MessageDemo2.
represent the command number (or ‘Instruction Code’, as it is referred
txt, it will appear rather long and complex. Thankfully,
to in the R503 datasheet, which is available for download along with
we will not need to worry about how it all works; instead,
this month’s code).
we’ll just use it as a tool for communicating with the R503.
In the RESPONSE section, the MessageFrameBytes received are
Essentially, you just need to define the command bytes
shown as RxMFB(1-9) and RxMFB(10-11). Note that RxMFB(7) is the
that you wish to send, and then observe the formatted
Identifier byte, which represents the type of message. Here, the value of
response on the terminal screen; an example being the
&h07 represents an ACKNOWLEDGE message (as conveniently shown).
screenshot shown in Fig.4.
Following RxMFB(9) are the Packet Data bytes which represent
More specifically, the variable PD_Qty needs to be set
the response from the R503 module. There will always be at least one
with the number of Package Data bytes to be sent, and then
the value of these bytes are defined in the array TxPD().
Then the subroutine TxCmdPkt is called, and the program
will go off and do its magic.
To see this in action, let’s again use AuraLEDConfig as
the command we want to send to the R503. Assuming you
haven’t edited the code in any way, scroll down to lines
156-7 (see Fig.5 to confirm the correct two lines).
You will see the first line sets PD_Qty to a value of 5,
which in turn means that the array TxPD(1-5) should
be set with the values of the five bytes to be sent. The
first byte in TxPD(1)=&h35 defines the AuraLEDConfig
command, with the four required parameters following in
TxPD(2-5). Now change the value of TxPD(4) from &h02
to &h01 and RUN the program again. If all is well, the red
LED should now be lit. Hopefully, this all makes sense,
and we recommend you try changing the LED’s behaviour
even further by adjusting the values in TxPD(2-5), as
defined in the R503 datasheet.
Length = Quantity of bytes in PACKAGE DATA and CHECKSUM
Remember to comment!
Fig.4. A screenshot of what the FP_MessageDemo2.txt program
outputs to the terminal screen. Here it shows the bytes communicated
when sending the command to turn on the blue ring-LED (also refer to
text from Part 1, page 61).
Practical Electronics | February | 2023
We will shortly be working through the enrolment process
of fingerprints, and then the subsequent searching. This
will involve sending a specific sequence of commands to
the R503, and observing the responses. To avoid having
to continually alter the value of PD_Qty depending on the
command being sent, and then also having to set up the
relevant number of Package bytes with the appropriate
byte values, we have pre-coded (and numbered) all the
necessary steps that we are going to be using. There are six
steps for enrolling, and three steps for searching.
Scroll up to line 118, and you will see step 1 defined
with PD_Qty=1 : TxPD(1)=&h01 which is the GenImg
command (more on this shortly). However, note that
51
Fig.5. Here, lines 156-7 in the
FP_MessageDemo2.txt program
code are not commented out.
These specific values define the
AuraLEDConfig command (and
associated parameters) meaning
this command is sent to the
R503 when the program is RUN.
currently the line is commented
out (with a ‘ character at the start
of the line).
Simply uncomment this line
(by removing ‘) to ensure that
when the program is RUN this is
the command that is sent. However, you must also comment out the
previous command used, in this case the AuraLEDConfig command
on lines 156-7 (by adding ‘ to the start of both lines). Note that the
exact position of the ‘ is irrelevant provided it’s before PD_Qty=.
Note also, for step 9 and AuraLEDConfig there are two lines that
need commenting (or uncommenting).
In summary, to correctly use FP_MessageDemo2.txt, uncomment
the one (or two) lines associated with the single command you wish to
send to the R503, and ensure all other commands are commented out.
Then RUN the program and observe the result on the terminal screen.
Enrolment
To register a new fingerprint, follow the six-step enrolment process:
1. Take an image of the finger (GenImg command)
2. Convert the image into a temporary Template and store it in
CharBuffer1 (Img2Tz command)
3. Taking a second image of the same finger (GenImg command)
4. Convert the second image into a second temporary Template and
store it in CharBuffer2 (Img2Tz command)
5. Generate a final Template based on averaging the two temporary
templates (RegModel command)
6. S tore the final Template in one of 200 Template slots
(Store command)
Fig.6. If no finger is placed on the sensor when the GenImg
command is sent, then an appropriate Confirmation Code
is shown. The GenImg command is defined by setting
TxPD(1)=&h01.
To begin the enrolment of a finger, uncomment step 1 in the program
code (line 118 if program unaltered) remembering to comment out
the AuraLEDConfig command (lines 156-7). RUN the code, and this
will send the GenImg command. You will probably see the output
shown in Fig.6. Note that although it was a VALID RESPONSE (no
corrupt data), the Confirmation Code, i.e. RxPacket(1),
shows as ‘No finger detected’.
Now, gently place the end of any finger over the R503’s
sensor and RUN the program again (keeping your finger on
the sensor!). This time, you should see the output as shown
in Fig.7. If not, reposition the finger and try again. It may
take several attempts while you get used to how hard to
press, and what position is best. What you are looking for
is the Confirmation Code to show Command execution
complete (ie, RxPacket(1) has a value of zero). When you
see this, you may take your finger off the sensor.
On successfully completing step 1 of the enrolment
process (take a fingerprint image) we can move onto step 2.
Uncomment the necessary line of code for step 2, remembering
to ensure that you comment out step 1. Then RUN the program
again. This should result in the screen shown in Fig.8. Because
the Img2Tz command in step 2 is simply moving the image
into internal memory (CharBuffer1), the chances are it will
complete successfully. However, if the fingerprint image is
too poor, then an appropriate message will be shown. Note
that the Img2Tz command (defined by TxPD(1)=&h02)
Fig.7. When the GenImg command detects a finger, the
Confirmation Code will show as Command execution
complete (RxPacket(1) will have a value of zero).
52
Practical Electronics | February | 2023
requires a single parameter. This parameter defines which
CharBuffer is used (1 or 2). Referring to Fig.8, you will see
that CharBuffer1 is being used because TxPD(2)=&h01.
Now continue to steps 3 and 4, which is effectively a
repeat of steps 1 and 2, but this time the fingerprint image is
stored in CharBuffer2 (defined with the value being sent by
RxPD(2) in step 4). Be sure to use the same finger as before!
Next, step 5 will combine CharBuffer1 and CharBuffer2
into a single fingerprint template, and hold it internally in a
buffer. This action is initiated with the RegModel command
defined by setting TxPD(1)=&h05. Uncomment the relevant
line of code, ensuring that the Confirmation Code returns
as Command execution complete.
If you have reached this point, then all is good with the
fingerprint captured. The only remaining task is to store
it in one of the R503’s 200 slots. Now uncomment step 6.
The value of TxPD(4) defines which slot is to be used. You
will see it has a hex value of &h22 (34 in decimal). RUN
the program and ensure the Confirmation Code returns as
Command execution complete. If so, this confirms that
the enrolment process has successfully completed; however,
any other message will guide as to what is wrong. If you do
run into an issue, the best thing is to start again at step 1.
Remember that this manual process of going through the six
steps for enrolment is just to explain what specific messages
need to be sent, and what each response should look like.
Enrol a different finger
Fig.8. The Img2Tz command requires a single parameter which is why
two Package bytes (highlighted) are sent.
Now that you have successfully enrolled a finger, it’s time to
enrol a different finger. So repeat steps 1-6, but at step 6, be sure
to change the value of TxPD(4) to a different slot value. This can
be set to any value between &h00 for slot 0, up to &hC7 for slot
199 (but avoid using &h22 again, otherwise it will overwrite the
previously stored fingerprint template). We recommend you enrol
several fingers but do keep a note of which finger is associated
with which slot number!
Checking Template slots
To check the number of slots currently in use in the R503 (ie,
how many slots contain a fingerprint template), you can use the
TempleteNum command (as spelt in the datasheet!). You can
uncomment line 160 in the code to activate this command, which
essentially sets PD_Qty=1 and TxPD(1)=&h1D; the answer (as a
hex number) is returned in RxPacket(3).
However, this is just the quantity of slots used, it doesn’t state
which slot numbers they are (and hence which are free to use).
To find out the used slots, there is the ReadIndexTable
command. This command is identified by setting TxPD(1)=
&h1F; it also has one parameter which we need to set to &h00.
This will return a list of 32 byte values into RxPacket(2-33),
as can be seen in Fig.9. The first byte value (ie, the contents of
RxPacket(2)) represents the first 8 slots (ie, slot numbers 0-7).
If any bit in RxPacket(2) is set (=1), then that slot number is
occupied (the least-significant-bit (lsb) represents slot 0, and the
most-significant-bit (msb) represents slot 7). Therefore, because
RxPacket(2) has a byte-value of &h00, it means that none of
the slots between 0 and 7 are occupied. Likewise, RxPacket(3)
represents slots 8-15, RxPacket(4) for slots 16-23, RxPacket(5)
for slots 24-31, and RxPacket(6) for slots 32-39.
However, as can be seen in Fig.9, RxPacket(6)=&h04, which
as an eight-bit binary value translates into: 0000 0100. Here, slot
32 status is represented by the lsb (which is zero), slot 33 status is
the next bit (also zero), but the next bit is set to 1 which represents
the status for slot 34. And if you now recall step 6 when you
registered the first finger, it was assigned to slot &h22, which in
decimal equates to the value 34.
If you did not follow the above in all its detail, don’t panic.
It is just to explain the steps that our final code will be made to
Practical Electronics | February | 2023
automatically work through to determine which slots are free,
and which are not. More on this next month.
Searching – theory
Searching is the action of comparing the current fingerprint image
with the templates that are stored in the template library (slots
0-199). The R503 will then respond back to the PicoMite as to
whether (or not) a match was found. If a match was found, then
the slot number is returned, along with a MatchScore value
(something that is not documented in the datasheet!).
To perform a search, follow three simple steps (we continue
numbering these steps from the six enrolment steps above):
7. Take an image of the finger (GenImg command)
8. Convert the image into a temporary Template and store it in
CharBuffer1 (Img2Tz command)
9. Search the template library (slots 0 to 199) for the temporary
Template just put into CharBuffer1 (Search command)
Before proceeding, ensure you have commented all commands
apart from step 7 (line 140). Then perform step 7 with one of
your enrolled fingers placed on the sensor. If you see a Command
execution complete status, then move onto step 8 (and remove
your finger from the sensor). Once again, you may need to try
several times to complete step 7 (just reposition very slightly
until the finger is detected). You are already familiar with step
8; it is exactly the same as step 2, as performed in the enrolment
process where the image is stored as a temporary Template in
CharBuffer1. When completed successfully, move onto step 9.
This will perform the Search command, and requires five
additional parameter bytes to be sent. These are poorly documented
in the datasheet, but essentially comprise the following:
n
TxPD(2) = the CharBuffer holding the temporary Template
(in this case, CharBuffer1)
n TxPD(3-4) = the StartPage (both need to be set to &h00 and
is effectively the starting slot number)
n
TxPD(5-6) = the PageNum (seems to represent how many slots
to search through). Setting it to 200 (ie, search all
slots) equates to the hex value &hC8. So, TxPD(5)
needs to be set to &h00, and TxPD(6) is set to &hC8
53
Fig.10 shows a typical output from the Search command
(when an enrolled finger is detected, and is found). There
are two important values in the response that we concern
ourselves with:
n
RxPacket(1) This needs a value of &h00 (ie, Command
execution complete). If no match
is found, then an appropriate message
is displayed.
n
RxPacket(3) This is the slot number that matches – in
Fig.10, this is slot &h22
Note that the MatchScore value is returned in RxPacket(5),
but I have been unable to find any information about it to
make it worth using. The only possible clue after many
hours searching online is that the higher the value, the
more confident the R503 is of the match.
Detecting different fingers
Now that you have seen the output of a search, repeat steps
7-9, but for different fingers that you have enrolled. You
should observe that on performing step 9, the response
value returned in RxPacket(3) represents the slot ID for
the finger that was enrolled into the slot (not forgetting
you must perform steps 7 and 8 first).
In use, I found it worked with 100% accuracy, but
I did find that sometimes it would not detect a finger
even when I was clearly placing a finger on the sensor. I
did discover though that when my finger was a little bit
damp, the finger was detected every time without fail (and
correctly identified). Perhaps, during the development
Fig.9. The ReadIndexTable command shows which of the 200
of this project, sitting for hours continually placing
fingerprint Template slots are occupied. Here, RxPacket(6) is the only different fingers on the sensor, I was making it too greasy,
non-zero value. See text for understanding how this relates to the slot
(or wearing out my fingerprints!).
numbers that are currently in use.
It could even be an earthing issue somewhere; running
from a laptop power supply, while holding the metallic
body of the R503 in one hand, and sensing a finger on the
other hand. I will look into this further to see if the cause
can be identified, and hence eliminated in the standalone
fingerprint reader that we’ll be building.
Summary
I really hope that you’ll be able to get the project up and
running to this point. It is a fantastic example of how
software is used to control hardware. Remember that there
are just six cables between the PicoMite and the R503, so
there isn’t much that can go wrong with the build. And with
correctly written software, a really complex process can be
performed – in this case, a biometric sensor capturing an
image of a finger, and converting it into a digital template
for cross referencing. As always, if you run into any issues,
then please do get in touch!
Next Time
In Part 3, we will put all the steps performed manually
above for the enrolment process into an easy-to-use program,
along with the ability to store a description (ie, a person’s
name) against each fingerprint template. Likewise, use
the search functionality so that it is possible to detect
and read a fingerprint, and then search for it against all
stored fingerprint templates. Once this is done, we can
then create a standalone fingerprint reader, complete with
its own touchscreen display.
Until then, stay safe, and have FUN!
Fig.10. The Search command will look for a match between the current
temporary Template (here in CharBuffer1) with all those stored in
the template library. Any match found will be shown with a Command
execution complete; along with the slot ID in RxPacket(3).
54
Questions? Please email Phil at:
contactus<at>micromite.org
Practical Electronics | February | 2023
|