This is only a preview of the February 2022 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 33: Using CRC with iButtons and the Micromite
A reminder from last month of what
iButtons look like. Note in the bottom
diagram the location of the family code
byte (01) and the CRC (89).
L
ast month, we explored how to
use a low-cost iButton (the DS1990)
with a Micromite. We discussed
the use of an iButton reader (or a pair of
wires) to electrically connect an iButton to
a single Micromite I/O pin (and ground).
By using MMBASIC’s built-in 1-wire
commands, we then showed how easy
it is to detect the presence of an iButton.
Micromite code
The code in this article is available
for download from the PE website.
64
We explained that different types of
iButton are available, which all have a
unique ID number which is 64-bits (8bytes) long. We highlighted that one of
those eight bytes represents the type
of iButton (ie, the Family Code), and
another byte represents what is referred
to as the CRC (cyclic redundancy check).
The iButtonDemo2.txt program from last
month reads the eight bytes from the
iButton (essentially reading 64-bits of
serial data on the 1-wire bus) and then
displays the result as eight hexadecimal
(hex) byte values. These eight bytes
form the unique ID number, and they
should be an exact match to the 8-byte
ID number that is engraved (in hex) onto
the iButton’s case. However, any contactbounce during the serial reading of the
64-bits will result in corrupt data values;
so how can we be 100% sure that the ID
number read is correct?
This month, we will begin by
explaining how the iButtonDemo2.txt
program extracts the 8-byte ID value,
and then go into detail as to how to use
the CRC byte to check whether the data
read is correct and valid (ie, no contact
bounce during the reading process),
or whether it is corrupted and hence
should be ignored. This is an important
topic to understand before introducing
a different type of iButton, the DS1971,
which incorporates 256 bits of EEPROM.
This specific EEPROM iButton allows
you to write up to 32 bytes of custom
data to it – for example, a person’s name.
This iButton will be explored next time
and in preparation for our Electronic
Combination Door Lock project, in which
EEPROM iButtons will be used as the
‘keys’, and a touchscreen display will
be used to show the name of the person
attempting to unlock the door (the name
being stored in EEPROM).
Let’s get started by explaining more
about last month’s downloadable program.
iButtonDemo2.txt
When you RUN iButtonDemo2.txt and
connect an iButton to the Micromite,
you should see that eight hex bytes
are displayed on the Terminal screen
(repeatedly while the iButton is present).
What you may notice is that for most
of the time, the eight hex byte values
displayed (on each line) are identical,
line-by-line; and they are also the same as
the eight hex values that are stamped onto
the iButton’s case. However, occasionally
you may see a line of different values
displayed, and this is simply due to
contact bounce (see Fig.1) – more on
this shortly.
Communication starts with the
Micromite (the ‘master’) sending a
command (ie, a series of pulses) on the
Fig.1. An example of the output from
iButtonDemo2.txt program while an
iButton is connected to the Micromite.
Note the last line of data shows the
impact of contact bounce as the iButton
was removed.
Practical Electronics | February | 2022
Fig.2. Comment
out these
three lines of
code from the
iButtonDemo2.txt
program to better
demonstrate
contact bounce.
1-wire bus. In our program, this is the
Read ROM command:
ONEWIRE WRITE iB_pin,1,1,&h33
If an iButton is present, then the initial
pulses provide parasitic power (see last
month) which powers the iButton’s
internal circuit long enough for it to
respond to the command it was sent.
This response is a series of pulses that
represent the data that needs to be sent
back to the Micromite, or to put it another
way, the iButton toggles the logic level on
the 1-wire bus in a controlled manner so
that the MMBASIC firmware can sample
the logic level on the 1-wire bus to receive
the data being sent by the iButton. Clearly
this all needs to be very precisely timed,
and thankfully, the MMBASIC firmware
deals with all of this for us, thereby making
iButton communication easy. Note that
when MMBASIC sees a response on the
1-wire bus, it sets the system variable
MM.ONEWIRE to a value of 1. However, if
there is no response detected on the 1-wire
bus, then it is assumed that no iButton is
present, and MMBASIC sets the system
variable MM.ONEWIRE to a value of 0.
The value of the MM.ONEWIRE system
variable is what we used in Demo1 when
demonstrating how to detect the presence
of an iButton. In Demo2, it is used with
an IF…THEN… command, which in turn, is
inside a DO/LOOP to continually look for
the presence of an iButton on the 1-wire
bus. Whenever an iButton is present,
the block of code inside the IF/ENDIF
section will read the iButton response
(eight bytes) and load the values into
eight variables, d1 to d8. This data read
is performed with the single line of code:
ONEWIRE READ
iB_pin,2,8,d1,d2,d3,d4,d5,d6,d7,d8
Practical Electronics | February | 2022
Once these variables are loaded, they
are re-sequenced, and then converted
into hex so that the layout matches the
eight hex bytes that are stamped on the
iButton’s case. To clarify, d8 contains
the CRC byte and is displayed on the
left (hex value 91 in Fig.1) followed by
the next 6-bytes of the ID number (d7 to
d2). These six bytes are formatted and
loaded into the string, iNew$. Finally,
variable d1 is displayed on the right
and this contains the Family Code byte
(hex value 14 in Fig.1, which represents
a DS1971 EEPROM iButton).
The line: IF iNew$=iOld$ THEN
is there to ensure that the eight hex
bytes are only displayed when the six
middle bytes read ‘this time’ match the
six middle bytes read ‘last time’. This
will remove a lot of contact bounce as we
will demonstrate shortly. Note that any
difference between successive reads with
the first byte displayed (d8, CRC) or the
last byte displayed (d1, Family Code) is
not filtered out (as can be seen in Fig.1).
pull the 1-wire bus to ground (and the
Micromite will then sample a low logic
level representing the value of 0). And
when the iButton needs to transmit a 1
data bit, it doesn’t need to do anything at
all since the pull-up resistor will ensure
that the Micromite samples a high logic
level (representing the value of 1).
This will all work correctly when the
iButton is electrically connected to the
Micromite; however, in reality (and at
the macroscopic level) there will be a
lot of contact bounce that occurs. What
this means is that the iButton is rapidly
altering between being in contact with the
Micromite, and not in contact at all. When
it is not in contact (during the ‘bouncing’),
the Micromite will sample as normal, but
will only see a logic high due to the pullup resistor. If this occurs across all eight
sampling timeslots (ie, bits) that form a
byte value, then the result seen by the
Contact bounce
To better demonstrate contact bounce,
EDIT the code and comment out the
three lines associated with the IF/ELSE/
ENDIF near the end of the DO/LOOP
(refer to Fig.2). Now RUN the program
and observe what happens when you
present an iButton; you should see a
lot more contact bounce in the form of
different line-by-line values (see Fig.3).
What you will probably notice is
that there are a lot more FF hex values
being displayed; we will now explain
the reason for this.
If you refer to the schematic (see Fig.8
from last month), you will see the 1-wire
bus is pulled high by a pull-up resistor.
When the iButton needs to transmit a 0
data bit, all it needs to do is to simply
Fig.3. An example output from the
modified iButtonDemo2.txt program to
better demonstrate contact bounce.
65
Fig.4. The 1-wire CRC generator in schematic form, as taken from Maxim’s DS1990 datasheet.
Micromite is going to be a binary value
of 11111111, or in other words, FF hex.
Hopefully this has explained the
issue of contact bounce, and has also
highlighted its effect on the data read
by the Micromite. What we now need
to understand is how to eliminate rogue
data received by the Micromite so that
we can be 100% certain that the 8-bytes
received are in fact a true (and correct)
representation of the iButton’s actual ID
number, as stamped on its casing. This
is where the CRC byte comes into play.
CRC
As already mentioned, the CRC byte is
part of the iButton’s 8-byte ID number,
and it can be used to check the validity of
the ID number received by the Micromite.
The simplest way to consider its purpose
is that when the other seven-byte values
received are passed through a specific
algorithm (defined by the original
manufacturer, Dallas Semiconductors)
the output (ie, answer) should be the
exact same value as the CRC byte. If it
is, then the 8-byte ID value received can
be considered as being 100% correct.
However, if the answer is different, then
the data received should be disregarded
(and considered corrupt, most likely due
to contact bounce).
So how exactly does the CRC checking
work? Unfortunately, the mathematical
theory behind it all is far too complex to
go into here, but the steps needed to be
performed to simulate the algorithm can
be explained relatively easily. For those
interested in the complexity behind it,
an online application note can be found
at: https://bit.ly/pe-feb22-max
Also, if you examine an iButton’s
datasheet, you will see reference to the
CRC, and mention that the maths is based
on the polynomial x8 + x5 + x4 + 1, which
in turn can be represented by a schematic
diagram – see Fig.4 (taken from the DS1990
datasheet). The reason the schematic is
recreated here is so that you can see some
connection with the following explanation
of the steps taken by the algorithm.
The CRC process
The complete CRC process will effectively
take the first seven bytes received (ie,
66
d1 to d7 as used in Demo2), and along
with the specific rules of the algorithm,
each of these bytes will be used in turn
to adjust the value of a variable that we
will call CalcCRC. By the time we have
used the last bit of the seventh byte (d7)
to adjust CalcCRC, the value of CalcCRC
should be the same as the CRC byte value
(d8). Furthermore, and for completeness,
if d8 is also used to adjust CalcCRC
(but only when CalcCRC has the same
value as d8; as it should if everything is
received correctly), then the final value
of CalcCRC will be 0. However, there is
no need to do this extra step as we can
simply stop at d7 and check that it has
the same value as d8.
We need to begin the whole process
by setting CalcCRC to an initial value
of 0, and then to apply the algorithm,
we need to work through each of the
8-bits (least significant bit (LSB) first)
of the first byte received (d1) and use
each bit to determine how the value of
CalcCRC is adjusted (more on exactly
what happens will be explained shortly).
This process is then repeated, with the
remaining bytes (d2 to d7), with each
byte continually adjusting the value
of CalcCRC. In simple terms, we need
to adjust the value of CalcCRC (which
starts at an initial value of 0) a total of 56
times (7-bytes, 8-bits per byte) to arrive
at the final answer that should match
the CRC value.
The CRC algorithm
This is where it starts to get a little trickier,
but please do be patient, take your time,
and try to follow things since it will prove
extremely useful to be able to understand
how things work here – not to mention,
it is very satisfying once understood!
Referring to Fig.4, consider the bits
representing the current value of CalcCRC
being put into the eight boxes, (MSB in
the 1st stage, and LSB in the in the 8th
stage). The bit-value of the 8th stage (ie,
the LSB of CalcCRC) needs to be XOR-ed
with the input data bit – let us call the
outcome the ‘XOR result’. Note that the
input data bit comes from the current
bit value from the data byte value being
passed (ie, from d1 to d7). If the XOR
result is a 0, then the 8-bits of CalcCRC
are simply shifted one place to the right,
resulting in a new value for CalcCRC.
However, if the XOR result is a 1, then
not only are the bits of CalcCRC shifted
to the right, but in addition, three bits
of CalcCRC (the bits in stages 1, 5, and
6) are also XOR-ed with 1. If you work
through the combinations of the XOR
truth table, you will see that this simply
means inverting these three bits.
To h e l p r e i n f o r c e t h e a b o v e
explanation, let us work through two
different scenarios – one where just a
simple shift of CalcCRC is required to
create the new value of CalcCRC, and
the other where we also need to invert
the relevant bits of CalcCRC to generate
its new value.
CRC example
For this example, let us assume that we
have already passed all 48-bits from d1
to d6, through the algorithm, along with
the first 6-bits from d7 (ie, bit 0 to bit 5),
and hence we now only need to apply
the last two bits (bit 6 and bit 7) from d7
into the algorithm – in other words, two
more CalcCRC values to generate before
comparing its final value with that of d8.
Let’s assume that the current value for
CalcCRC is hex 76 (in binary: 01110110)
and let us also use a value of hex 00 for
d7 (in binary 00000000).
So, the LSB (bit-0) from CalcCRC
(01110110) needs to be XOR-ed with the
input data bit which now comes from bit
6 of d7 (00000000). The result of 0 XOR
0 is 0 which means we just need to shift
the CalcCRC bits (currently 01110110)
one place to the right to generate its new
value of: 00111011.
Now let’s do the final pass by using the
new value of CalcCRC generated above
(00111011), and bit 7 of d7. Hence,
the LSB (bit 0) from CalcCRC (now
00111011) needs to be XOR-ed with
the input data bit which now comes from
bit 7 of d7 (00000000). The result of
1 XOR 0 is 1, which means we not only
need to shift the CalcCRC bits (currently
00111011) to the right to generate its
new value of: 00011101, but we also
need to invert the relevant bits (shown
in bold and underlined) to generate the
new value of: 10010001.
Practical Electronics | February | 2022
So, the final value of CalcCRC is 10010001 which is hex
91. This can now be compared to d8, and if it matches, we can
assume the 8-byte ID number read from the iButton is correct.
In the example just shown, we defined the current value of
CalcCRC as hex 76. This was not a value chosen at random,
but was chosen intentionally as it is the actual value that would
have been reached for CalcCRC after passing the first 54 bits
into the algorithm (and with everything operating correctly)
when using the following values:
d1=’14’
d2=’EC’
d3=’DE’
d4=’DC’
d5=’08’
d6=’00’
d7=’00’
So why use these values? The observant among you will see
that these are the exact same values as in the screenshot from
Fig.1 (or Fig.3). Remember that the CRC byte (d8) is displayed
as the left-hand byte in each row, and is indeed showing a
hex value of 91, and hence here we can be assured that the
variables d1 to d8 all contain correctly read data values.
Furthermore, d1 (the Family Code byte value shown on the
right of each row) is showing a hex value of 14, and this
represents a DS1971 256-bit EEPROM iButton (the iButton
we will be using later).
iButtonDemo3.txt
The above example of performing the final two passes of the
algorithm should help you understand things much better (if
not, take a break, and read it again another time!).
For an extreme challenge, why not start at the beginning,
and work through all 56 passes of the algorithm using the
above values for d1 to d7 (and using 0 as the initial CalcCRC
value, as would be required). This would clearly be a lengthy
task to perform manually, and therefore we have created a
download for you (iButtonDemo3.txt) which shows the new
value of CalcCRC after each stage (see Fig.5). In fact, it also
passes d8, showing that the final result of CalcCRC is indeed
0 (but only when d1 to d8 contain correct values). Download
the program and note that the code is commented throughout,
but don’t worry if you don’t understand fully how it works.
There are two lines of code in the program that need
highlighting to understand what is going on:
1. CalcCRC=CalcCRC>>1
This line simply shifts the bits in the variable CalcCRC one
place to the right as is the requirement in the CRC algorithm.
Note that what was contained in bit 0 (the right-hand bit) is
simply discarded, and the new MSB (ie, bit 7 in our case)
is set to 0. As an example, if CalcCRC contains the binary
value 10111101, then the result of the above >>1 would
be 01011110
2. CalcCRC=CalcCRC XOR &h8C
This line has the effect of inverting bit 7, bit 3, and bit 2, which
sometimes is a requirement in the CRC algorithm. The hex
value 8C (in the above line of code) equates to 10001100 in
binary. So, if CalcCRC contains the binary value 11111111,
then the above becomes:
11111111 XOR 10001100 equals 01110011
Which has only inverted the bits highlighted in bold.
Likewise, if CalcCRC contains the binary value 00000000,
then the above becomes:
Practical Electronics | February | 2022
Fig.5. The iButtonDemo3.txt program displays the new value of
C al cC R C after each pass of the CRC algorithm.
00000000 XOR 10001100 equals 10001100
Which, again, has only inverted the bits highlighted in bold.
The reason for going into the detail of the CRC checking is
that it is essential to ensure that any serial data read from an
iButton is 100% correct (ie, free of contact bounce). With the
DS1990 ID-only button, we only have the 8-byte ID number
to concern ourselves with; however, we will be using the
DS1971 EEPROM iButton for use in our upcoming Electronic
Combination Door Lock project, in which we will also need
to read 32 bytes of custom data (containing a person’s name).
You can see that when reading 32 bytes there is much more
chance of contact bounce during the serial read compared
to reading just eight bytes; hence, CRC checking is a critical
part of the solution.
There are 32-bytes available in the DS1971, so the concept
will be to use the first 31 bytes to store the person’s name, and
then use the 32nd byte to store the CRC value (much like the
last byte in the 8-byte ID number for any iButton is the CRC
byte programmed in by the manufacturer).
The obvious question is how do we generate the CRC value
to be stored in byte-32 of the EEPROM iButton? Helpfully, the
CRC algorithm can be used to generate a CRC byte value after
passing it any number of bytes; so we can therefore pass 31bytes into the algorithm, and generate the final value of CalcCRC
which can then be written as byte 32 into the EEPROM.
Next time
Having got a grasp of dealing with contact bounce, next month we
will explore the DS1971 256-bit EEPROM iButton and demonstrate
how to write 32-bytes of custom data into EEPROM (including
the CRC byte value that we need to generate), along with how
to read this data back
into the Micromite –
Questions? Please email Phil at:
error free.
contactus<at>micromite.org
Until then, stay
safe, and have FUN!
67
|