ESP32: How to change and set the Wi-Fi MAC Address

ESP32 Tutorial: Wi-Fi MAC Address Get and Set

Abstract

Every network-enabled device, including the ESP32, has a unique Media Access Control (MAC) address. The ESP32 actually has two MAC addresses: one for Wi-Fi and one for Bluetooth. This tutorial shows how to programmatically retrieve the default Wi-Fi MAC address and how to permanently set a custom, user-defined MAC address for your ESP32 Wi-Fi interface using the Arduino framework.

1. Introduction to Real-Time Servo Control

In the realm of networked devices, every piece of hardware requires a unique identifier to communicate effectively. For the ESP32—a powerful microcontroller that is the backbone of countless IoT projects—this identifier is the Media Access Control (MAC) address.

A MAC address is a permanent, 48-bit (6-byte) serial number burned into the device’s hardware at the factory, often referred to as the default or base MAC. The ESP32 actually maintains two separate MAC addresses: one for its Wi-Fi interface and one for its Bluetooth interface.

Understanding how to manage these addresses is crucial for various networking tasks, including:

  • Network Access Control: Implementing MAC address filtering on a router to restrict access to known devices.

  • Device Tracking: Identifying a specific device consistently within a large network.

  • Testing and Security: Temporarily changing the device’s identity for testing or privacy reasons (known as MAC spoofing).

This tutorial provides a foundational guide for beginner ESP32 developers, demonstrating the simple Arduino code needed to both programmatically retrieve the default Wi-Fi MAC address and, more importantly, how to use low-level Espressif functions to permanently set a custom, user-defined MAC address for your project.

2. Retrieving the Default MAC Address

The default Wi-Fi MAC address is unique and stored in the ESP32’s internal memory (eFuse). You can retrieve it using the WiFi.macAddress() function after initializing the Wi-Fi module in Station mode (WIFI_STA).

Code to Get MAC Address

				
					#include <WiFi.h>

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println("--- Reading Default Wi-Fi MAC Address ---");
  
  // 1. Initialize Wi-Fi in Station mode (required to read the MAC)
  WiFi.mode(WIFI_STA); 
  
  // 2. Retrieve the MAC address as a String
  String macAddress = WiFi.macAddress();
  
  Serial.print("Default MAC Address: ");
  Serial.println(macAddress);
  Serial.println("------------------------------------------");
}

void loop() {
  // Nothing to do in the loop
}

				
			

3. Setting a Custom MAC Address

You might need to set a custom MAC address for specific applications, such as MAC address filtering on a router or for network security reasons. The WiFi.mode() and esp_wifi_set_mac() functions are used together to override the default address.

3.1 Important Notes on Custom MACs

  1. MAC Format: The MAC address must be exactly 6 bytes (48 bits) in hexadecimal format. It is conventionally written as six pairs of hexadecimal digits separated by colons or hyphens (e.g., AA:BB:CC:11:22:33).
  2. Multicast/Local Bit: For custom MAC addresses, the second least significant bit of the first byte should typically be set to ‘1’ to indicate a Locally Administered Address. A common convention is to use addresses starting with 02: or 0E: (e.g., 02:FF:AA:BB:CC:DD).

3.2 Code to Set Custom MAC Address

We use the low-level Espressif function esp_wifi_set_mac(), which requires the MAC address to be passed as an array of 6 bytes.

				
					#include <WiFi.h>
#include <esp_wifi.h> // Required for esp_wifi_set_mac()

// --- DEFINE YOUR CUSTOM MAC ADDRESS HERE ---
// Note: This MAC must be provided as an array of 6 bytes (hex).
// The example MAC starts with 0x02 to denote a Locally Administered Address.
uint8_t customMacAddress[] = {0x02, 0xDE, 0xAD, 0xBE, 0xEF, 0x01}; 

void setup() {
  Serial.begin(115200);
  delay(1000);
  
  // 1. Initialize Wi-Fi in Station mode
  WiFi.mode(WIFI_STA); 
  
  // 2. Set the custom MAC address using the low-level function
  // The first argument specifies the Wi-Fi interface (WIFI_IF_STA for Station mode)
  esp_err_t err = esp_wifi_set_mac(WIFI_IF_STA, customMacAddress);

  if (err != ESP_OK) {
    Serial.printf("Failed to set MAC address! Error: 0x%x\n", err);
  } else {
    Serial.println("Custom MAC Address set successfully.");
  }
  
  // 3. Verify the new MAC address
  String newMacAddress = WiFi.macAddress();
  Serial.print("Verified New MAC Address: ");
  Serial.println(newMacAddress);
  
  Serial.println("------------------------------------------");
}

void loop() {
  // Optional: Add a Wi-Fi connection attempt to confirm functionality
  // WiFi.begin("SSID", "PASSWORD"); 
}

				
			

4. Source Code

This project involves two distinct but related code segments: one for reading the MAC and one for writing a custom MAC. Both rely on the standard Wi-Fi library (WiFi.h) and proper initialization of the Wi-Fi mode.

4.1 Retrieving the Default MAC Address

The key to accessing the MAC is initializing the Wi-Fi stack.

Code LinePurpose
#include <WiFi.h>Includes the standard Arduino library for Wi-Fi functionality.
WiFi.mode(WIFI_STA);Critical Step: Initializes the Wi-Fi module in Station mode. The Wi-Fi stack must be started for the MAC address to be accessible by the software functions.
String macAddress = WiFi.macAddress();Retrieval: This high-level Arduino function queries the Wi-Fi stack and returns the currently active MAC address as a String, which is easily printable to the Serial Monitor.

4.2 Setting a Custom MAC Address

Setting a custom MAC requires using a lower-level function specific to the Espressif SDK (esp_wifi.h), as the basic Arduino Wi-Fi library does not include a direct setter function.

Code LinePurpose
#include <esp_wifi.h>Includes the required low-level Espressif header for MAC manipulation.
uint8_t customMacAddress[] = {...};Custom MAC Definition: Defines the desired MAC address as an array of 6 bytes (uint8_t), where each pair of hexadecimal digits is an element (e.g., 0xAA, 0xBB, ...).
WiFi.mode(WIFI_STA);Initialization: Still required. The Wi-Fi mode must be set before attempting to override the MAC address.
esp_err_t err = esp_wifi_set_mac(WIFI_IF_STA, customMacAddress);The Setter Function: This is the core low-level call:<ul><li>WIFI_IF_STA: Specifies that the change applies only to the Station interface.</li><li>customMacAddress: Passes the 6-byte array containing the new MAC.</li><li>esp_err_t: The function returns an error code (ESP_OK if successful) for debugging.</li></ul>
String newMacAddress = WiFi.macAddress();Verification: Calls the standard Arduino getter function (WiFi.macAddress()) again to confirm that the esp_wifi_set_mac command successfully overrode the default address.

Note on Persistence: The custom MAC address set by esp_wifi_set_mac() is stored in the ESP32’s RAM and is temporary. It will not persist through a power cycle or reset. If a permanent custom MAC is required, the esp_wifi_set_mac() function must be called every time the ESP32 executes the setup() function.

5. Hands-On Lab Recap

You’ve learned how to manage the ESP32’s Wi-Fi MAC address:

    • Getting the MAC: Use macAddress() after setting WiFi.mode(WIFI_STA).
    • Setting a MAC: Use the low-level function esp_wifi_set_mac(WIFI_IF_STA, mac_array) along with an array of 6 bytes defining your desired MAC address.
    • Persistence: The custom MAC address is set in RAM and will persist until the next reset/reboot, at which point it must be set again in the setup()

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top