I have a Micropython ESP32 sending an ESP-NOW message to an Arduino ESP32. The message leaves the Micropython as bytearray(b'87') - a value of 87 - but comes out of the Arduino as data =14136. I'm using the stock receive code of:
int data=0;
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&data, incomingData, sizeof(data));
If I convert the 'data' variable to a char I get the first value of the integer I want (8). I'm not sure if I'm running into a Micropython- Arduino type mismatch. Thanks
I don't think so as I'm just sending an integer from Micropython. That example defines the struct on both ends to encode/decode the message. I suspect it maybe Micropython encoding with UTF-8. Bit of a hardware corner I'm backed into since the sender needs Micropython for it's asyncio properties, and the receiver is an LCD display without mature Micropython support.
Playing around more with it, if I modify 'data' from type int to String, I get the correct value, although the serial monitor output has trailing characters I assume from the rest of the bytearray.
int n;
String s;
void assign87(byte *b) {
*b++ = '8';
*b++ = '7';
}
void setup() {
Serial.begin(115200);
// delay(1500); // may need this
assign87((byte *)&n);
assign87((byte *)&s);
Serial.println(n);
Serial.println(n, HEX);
Serial.println(s);
Serial.println(s.length());
}
void loop() {
}
I get
14136
3738
0
Does the int make sense now? I did not reproduce your String result, but I can if I change the declaration to String s = "ABCD";
87CD
4
But only on ESP32, not on Uno. This is actually a trap, an invalid way of writing to the internal implementation of a String on some boards.
The data is coming across fine. You need to have a more accurate definition of the "shape" of the data, defined in C++. It could be a struct. In C++, an "array of bytes" that represents a string must be NUL-terminated. Details like that.
Thank you, that is helpful. Your code output line as is ' Serial.println(n);' matches 4 input test points I tried. Reversing your function to output '87' from an input of '14136' is not jumping off the page to me but I will look at it more deeply in the AM.
Thank you. I think that's correct as well but the code snippet seems to add the null terminator 0 in the middle of whatever is incoming from Micropython. The MP docs say it sends "msg : string or byte-string up to espnow.MAX_DATA_LEN (250) bytes long" and the print output in MP is bytearray(b'87').
@coaster what you have in Python is a byte string which can converted to a list then each character transmitted one at a time.
byte_string = b'87'
ser.write(list(byte_string))
One way of checking this out is using the following which will echo the value back to the sender
int data=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
if (Serial.available () > 0){
data=Serial.parseInt ();
Serial.println(data);
}
}
I didn't get that result initially when I print the 'byte_string' list in Micropython, but I do get the behaviour you describe with the modify the line to list(byte_string.decode('utf-8')) .
In case anyone comes across this problem of having Micropython talk to Arduino with ESP-NOW, the solution that seems to be working best for me was to convert to JSON. In Micropython the sender puts out a JSON object via ESP-NOW with the data I need:
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
// Convert the incoming byte array to a string
data = String((char*)incomingData);
// Allocate memory for the JSON document
StaticJsonDocument<250> doc; // Adjust the size based on your expected JSON structure
// Deserialize the JSON string into the document
DeserializationError error = deserializeJson(doc, data);
// Access the values from the parsed JSON
upper_tank_percentage = doc["upper_tank_percentage"].as<int>();
lower_tank_percentage = doc["lower_tank_percentage"].as<int>(); // Make sure this key exists in your JSON
battery_voltage = doc["battery_voltage"].as<int>(); // Ensure this key matches your JSON structure