Thanks to Rui and Sara Santos for their book MicroPython ESP32 and ESP8266. I purchased 3 DoIT ESP32 DEVKIT V1 boards ($8 per) from Banggood and have done Module 1-2 and most of 3 before getting sidetracked. I hope people can help with this.
QUESTIONS
1. The “byte string” returned from the machine.unique_id instruction has information both in hex (eg \xcb) and in ASCII (eg. n). Knowing almost nothing about any form of Python, how do I take this “byte string” and format it so as to display only a string of hex numbers?
2. When reading the pre-programmed MAC address information contained in the EFUSE from each board, the result in the high 24 bits has an extra 2 hex digits which are not part of the MAC address. Are they a checksum? If not, what do they signify.
Problem: How to identify each board since the boards look completely identical. I can see absolutely no difference in labelling on either the board itself or on the ESP32-VROOM module. To differentiate, I labelled them 1 – 3 with a Sharpie. BUT, how to do this electronically? All boards have firmware v1.18.
A Clue from MicroPython Documentation, Release 1.18, page 60, Miscellaneous functions: machine.unique_id()
“Returns a byte string with a unique identifier of a board/SoC…In some MicroPython ports, ID corresponds to the network MAC address.” This is true for these particular boards.
Using CODE1 below, all 3 boards return a consistent “byte string” (using either Mu or Thonny)
board1 b’\xec\x94\xcbnF\xe8′
board2 b’\xec\x94\xcbp$4′
board3 b’X\xbf%\x93\xd2h’
Then I used the example from MicroPython Documentation, Release 1.18, page 393: Accessing peripherals directly via registers, to learn how to read and print out the two EFUSE registers programmed with the WIFI MAC: ESP32 Technical Reference Manual (Version 4.6), page 518.
All 3 boards return consistent data:
board1 0x1aec94 0xcb6e46e8
board2 0x9bec94 0xcb702434
board3 0xfc58bf 0x2593d268
The first 6 hex digits (example: 1aec94) are the higher 24 bits from EFUSE register EFUSE_BLK0_RDATA2_REG. The second group of 8 hex digits (example cb6e46e8) are the lower 32 bits from EFUSE register EFUSE_BLK0_RDATA1_REG.
Assuming a MAC address of 48 bits, or 12 hex digits, I did an OUI search (Organizationally Unique Identifier), not using the first 2 digits from the higher group. This search confirmed that these numbers really were the MAC.
An OUI search on ec:94:cb returns Espressif Inc as the company registering that sequence in April 2021. An OUI search on 58:bf:25 likewise returns Espressif Inc, registering that sequence in June 2021
The machine.unique_id() data can, painfully, be turned into those same 12 digit MAC addresses. Example (board1, for a MAC address of ec:94:cb:6e:46:e8)
b’\xec = ec
\x94 = 94
\cb = cb
n = 6e (from ASCII table, symbol to hex)
F = 46 (from ASCII table, symbol to hex)
\e8 = e8
CODE1:
# Machine ID rr 3/17/22
# get unique id from DoIT ESP32 DEVKIT V1 boards MicroPython firmware v1.18
import machine
f_value = machine.unique_id()
print(f_value)
CODE2:
# ReadMemory2 3/21/22 rr
# read programmed WIFI MAC address from DoIT ESP32 DEVKIT V1 boards firmware v1.18
# see example MicroPython Documentation Release 1.18 page 393
# called 8.2.3 Accessing peripherals directly via registers# Absolute address information from ESP32 Technical Reference Manual Version 4.6, pages 515-518
from micropython import const
from machine import mem32
EFUSE_BLK0_RDATA1_REG = const(0X3FF5A004)
EFUSE_BLK0_RDATA2_REG = const(0X3FF5A008)
print(hex(mem32[EFUSE_BLK0_RDATA2_REG] & 0xffffffff)) # MAC upper 24 bits
print(hex(mem32[EFUSE_BLK0_RDATA1_REG] & 0xffffffff)) # MAC lower 32 bits
Both Questions Are RESOLVED
1. From a DoIT ESP32 DEVKIT V1 board is the “byte string” returned by machine.unique_id the 48 bit (12 hex digits) MAC (Media Access Control) address, which has been programmed into each board? YES
2. The programmed MAC address (in readable EFUSE registers) is 56 bits. The lower 48 bits are the MAC address. But what do the upper 8 bits (2 hex digits) represent?
They represent a checksum of the MAC address.
The answer was right in front of me. From the Espressif ESP32 Technical Reference Manual (Version 4.6), or ESP32 TRM, page 507:
WIFI_MAC_Address, 56 bit, …, WI-FI MAC address and CRC.
Or: ESP32 TRM page 518: The BLK0_RDATA2_REG (the “R” means readable) describes this register as WIFI_MAC_CRC_HIGH
Or from: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/system.html#mac-address
(scroll down to Custom MAC address in eFuse)
MAC address 48 bits
MAC address CRC8 bits CRC-8-CCITT, polynomial 0x07
There are Micropython code example to calculate CRCs, but using an online CRC8 calculator was much easier: https://tomeko.net/online_tools/crc8.php?lang=en
All three 48 bit MAC addresses returned the correct 8 bit CRC result.
unique ID CRC + MAC Computed CRC
b’\xec\x94\xcbnF\xe8′ 0x1aec940xcb6e46e8 1a
b’\xec\x94\xcbp$4′ 0x9bec940xcb702434 9b
b’X\xbf%\x93\xd2h’ 0xfc58bf0x2593d268 fc
Hi.
Take a look at this discussion and see if it helps convert it to a human-readable format: https://github.com/micropython/micropython/issues/3115
I also found this that might help: https://stackoverflow.com/questions/4959741/python-print-mac-address-out-of-6-byte-string
Regards,
Sara
Thank you Sara. These are good clues for what I need to learn.
It was good to read that “This is just how Python works: bytes objects are printed using ASCII characters where possible (ie if the byte is printable), otherwise it uses the hex notation.”
I would have never guessed that.
Those clues from Sara really helped. I found some working code for this problem at https://stackoverflow.com/questions/55027969/convert-byte-string-in-micropython
Revised CODE1
# Machine ID2 rr 3/25/22
# get unique id from DoIT ESP32 DEVKIT V1 boards MicroPython firmware v1.18
# 2 formatting clues from Sara Santos of RNT below
# https://github.com/micropython/micropython/issues/3115
# https://stackoverflow.com/questions/4959741/python-print-mac-address-out-of-6-byte-string
# another clue then found at https://stackoverflow.com/questions/55027969/convert-byte-string-in-micropython
# and its code used below, see answer by stanely Mar 24, 2021
import machine
import binascii
id_value = machine.unique_id()
mac_str = binascii.hexlify(id_value).decode() # output all hex
mac_str2 = binascii.hexlify((id_value), ‘:’) # insert colons
print(id_value)
print(mac_str)
print(mac_str2)
OUTPUT RESULT (from board 2)
b’\xec\x94\xcbp$4′
ec94cb702434
b’ec:94:cb:70:24:34′
So the machine.unique_id for this type of board really is its MAC address.
Hi again.
Thanks for sharing that information in such an organized way. This will definitely be useful for other readers, and for me as well.
Thank you.
I’ll mark this issue as resolved. If you need further help, you just need to open a new question in our forum.
Regards,
Sara