Setting a target MAC address for ESP-NOW fails on one esp - why?

Hi,

let me describe the scenario first, I have multiple ESP32 which are planned to be working together.

One of them is the SERVER. The server got its mac address set hardcoded to:

uint8_t ServerMACAddress[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0xFF};

the CLIENTS set their MAC address by a value read from a potentiometer,
declaration top of the code:

uint8_t customMACAddress[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

and modification in setup()

  // read value from potentiometer and map it to 16 possible values
  IDpotValue  = map(analogRead(IDpotPin), 0, 1000, 0, 15);
  // set the last digit of the MAC address
  customMACAddress[5] = IDpotValue;
  // set the local MAC address
  esp_wifi_set_mac(WIFI_IF_STA, &customMACAddress[0]);

so the last digit wil be changed to a value between 0 and F

Until here there is no problem, code works, server receives data and with the first message the IDpotValue from the client(s).

Now I want to make the server respond to that message and am trying to set the target mac address to the id where the message came from.

So same procedure on server side, top of the code:

uint8_t clientMACAddress[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

and in the receiption/response code:

clientMACAddress[5] = receivedClientID;

// trying to send the message:
esp_err_t result = esp_now_send(clientMACAddress, (uint8_t *) &comData, sizeof(comData));

The transmitted data are ints, BUT the message sending fails. No matter if I use the received int or do it manually by like clientMACAddress[5] = 14.

However if I hardcode the clientMACAddress to
uint8_t clientMACAddress[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0E};

The message sending succeeds.
What am I doing wrong here ?

Now some last words because it probably comes up:
Yes I know changing the MAC addresses isn't ideal but I

a) don't want to fetch each MAC from every (new) mcu
b) don't want to flash each mcu with a specific code
c) don't want a huge overhead of pairing code that involves even BLE, because I need the flash space

IF there is a way of pairing without that, I am of course ok with that but all articles and descriptions I found about it (for now) are either using fetched MAC addresses or BLE for initial pairing.

analogRead(IDpotPin) can go over 1000 (all the way to 4095 on an ESP32 depending on how it's configured) so you can get more than 15 from the map call. if you really want to limit the output between 0x00 and 0x0F then use the constrain function

  // read value from potentiometer and map it to 16 possible values
  IDpotValue  = map(analogRead(IDpotPin), 0, 1000, 0, 15);
  IDpotValue = contrain(IDpotValue, 0, 15);

probably something in the code you did not share ➜ Don't post snippets (Snippets R Us!)

documentation says:

see: Wi-Fi - ESP32 - — ESP-IDF Programming Guide v5.2.1 documentation

--> do it in the correct order
--> check the MAC after you tried to set it
--> when you post a complete code (Proof of Concept) some could check it.

2 and 3 are not related but you brought me to an idea.
What I was missing or set it at the wrong place... the peer has to be set and I did that in setup, which obviously is too early in the response case, because the ID from the sender isn't known there yet.

So for whoever comes across my POST, don't forget to add this at the right place:

  memcpy(peerInfo.peer_addr, clientMACAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }

Yes constrain might be a good addition here, even though the pots are all the same I noticed the analog in got some tolerances especially during running time.
I'd like a more accurate way for setting an id but digital solutions that came to my mind consume a lot more pins and a pot allows a quick dynamical change. So at the moment the ideal position per id is somewhere in the middle of a 16-17° angle. Maybe there are some pots with fixed steps but probably not in the proportions I need it. ~1cm²

I think the ESP32 comes with a unique MAC address - don’t they ? (Or a serial number you could use without a pot)

Yes, but.. bottom of the OP :slight_smile: I would use it if it wouldn't blow up the code.

plus you can't change the id then dynamically without reflashing

Why would you need to change it ?

Because the clients are going to be part of groups, so in case one client is broken or battery down or whatever technical issue you can use another client to replace this position.
To put it differently, there are more pro arguments setting the mac address, than pro using hardware specific -> in my project case.

I see your point but I could make the opposite argument with an adaptative process where you have a centralized admin interface on the server and when a new device registers with the server you can authorize the devuce and assign a role / credentials / name.

That’s why devices do come with a uniqueID.

What I understand up to now is you want to have an "easy to change" identifier.
The identifier should be changeable by hardware.
You have chosen a potentiometer - sounds weird to me - but ok. I would have chosen dip switches if it has to be hardware.

But I wouldn't use the MAC as identifier at all. I would send the ID as part of the payload and just send broadcasts to the network. Or if for any reason a broadcast doesn't fit well, I would introduce some automatic registration of devices/nodes.
Each node could broadcast a start message ("hi, i'm node ID 16 now you know my mac").
The main device could send a confirmation of the registration.

Dip switches waste a pin for each switch and you need 4 to set 16 variants. Unless you have enough gpio to spare, dip switches are not a too good option.

Your description is exactly what I planned but I couldn't figure out how to get the mac address from client (peer) , didn't work with esp_now_peer_info / peer.addr. So I have chosen the workaround.

of course, it is just that the "server" for this project is pretty limited and not really designed for comfortable human interaction