The Allegro A31301 is a high-precision magnetic angle sensor that communicates via I²C. One of the great advantages of the A31301 sensor is that its I²C address is configurable (16 with external resistors and 127 with programming). By default, it uses the I²C EEPROM address 0x6F, but in some applications you may want to change this — for example, if you have multiple A31301 sensors on the same I²C bus.
This guide explains how to change the I²C address stored in the EEPROM of the A31301 using an ESP32 and the Wire library.
The following has been made on a breadboard with an ESP32 Firebettle 2 and a small home made breakout board for the A31301.

Here is how the A31301 has been wired on the ESP32:

First, the A31301 must be powered. Since the sensor is a low power device powered in 3.3V, it can be connected to the ESP32 regulator without any problem. Pins SA0 and SA1 have to be connected to VCC, so the device will respond to the peripheral address stored in the EEPROM.
The A31301 stores its configuration, including the I²C address, in an internal EEPROM. To modify EEPROM values, you must use indirect access registers, following the device’s EEPROM write procedure:
The EEPROM address that stores the I²C address is found in the device datasheet (page 35): 0x0015.
Here’s a complete example sketch that performs the I²C address change sequence:
#include <Wire.h>
#define A31301_ADDR 0x6F // Default I²C address
// Read two bytes from a register
uint8_t read(uint8_t address, uint8_t reg_addr, uint8_t* msb, uint8_t* lsb) {
Wire.beginTransmission(address);
Wire.write(reg_addr);
if (Wire.endTransmission(false) != 0) {
Serial.println("ERROR NACK ?");
return 1;
}
Wire.requestFrom(address, (uint8_t)2);
if (Wire.available() != 2) {
Serial.println("ERROR: Should read 2 bytes");
return 2;
}
*msb = Wire.read();
*lsb = Wire.read();
return 0;
}
// Write two bytes to a register
uint8_t write(uint8_t address, uint8_t reg_addr, uint8_t msb, uint8_t lsb) {
Wire.beginTransmission(address);
Wire.write(reg_addr);
Wire.write(msb);
Wire.write(lsb);
if (Wire.endTransmission() != 0) {
Serial.println("ERROR NACK ?");
return 1;
}
return 0;
}
void setup() {
Serial.begin(115200);
delay(1000); // Secure power-on delay
Serial.println("\n\n\n ::::: Change EEPROM I²C address :::::");
Wire.begin();
// 1. Write Access Code
Serial.println("1. Write Access Code");
write(A31301_ADDR, 0x3E, 0x43, 0x55);
write(A31301_ADDR, 0x3E, 0x53, 0x54);
// 2. Load EEPROM target address (0x0015 = I2C address location)
Serial.println("2. Load INDIRECT_WR_ADDR with EEPROM target address");
write(A31301_ADDR, 0x02, 0x00, 0x15);
// 3. Load EEPROM data to be written (new I2C address)
// Example: new address = 0x2A
Serial.println("3. Load INDIRECT_WR_DATA registers with new address");
write(A31301_ADDR, 0x04, 0x00, 0x01); // Data MSB
write(A31301_ADDR, 0x06, 0x2A, 0x00); // Data LSB (0x2A = new I2C addr)
// 4. Invoke extended write
Serial.println("4. Start EEPROM write");
write(A31301_ADDR, 0x08, 0x80, 0x00); // Set EXW bit = 1
// 5. Wait until write completes (poll WDN bit)
Serial.println("5. Waiting for EEPROM write to complete...");
uint8_t WDN = 0;
do {
uint8_t msb, lsb;
read(A31301_ADDR, 0x08, &msb, &lsb);
WDN = lsb & 0x01;
} while (!WDN);
Serial.println("EEPROM write complete. Address changed.");
Serial.println("Power-cycle the device for the new I2C address to take effect.");
}
void loop() {}
0x3E send the required access codes (CUST):0x3E ← 0x43 0x55
0x3E ← 0x53 0x54
This sequence unlocks EEPROM writes.
Select target EEPROM address
The target EEPROM word address (here 0x0015) is loaded into INDIRECT_WR_ADDR (register 0x02).
Load data to write
The new I²C address value (e.g., 0x55) is written into the INDIRECT_WR_DATA_MSB and LSB registers (0x01 and 0x2A).
Trigger the write
Writing 0x80 0x00 to INDIRECT_WR_STATUS (register 0x08) sets the EXW bit, which starts the EEPROM write.
Poll the WDN bit
The write-done bit (WDN) indicates when the operation has completed. The code polls this bit until it becomes 1.
Once the device restarts, you can scan your I²C bus (using an I²C scanner sketch) to confirm that the A31301 now appears at its new address:
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(115200);
Serial.println("Scanning I2C bus...");
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
Serial.print("Found device at 0x");
Serial.println(addr, HEX);
delay(5);
}
}
}
void loop() {}
| Step | Action | Register | Description |
|---|---|---|---|
| 1 | Write access codes | 0x3E |
Unlock EEPROM write |
| 2 | Set EEPROM address | 0x02 |
Target = 0x0015 |
| 3 | Write data | 0x04 / 0x06 |
New I²C address |
| 4 | Trigger write | 0x08 |
Set EXW bit |
| 5 | Wait for completion | 0x08 |
Poll WDN bit |
After this sequence and a power cycle, your A31301 sensor will respond to the new I²C address you programmed into its EEPROM.