I've been trying to send 2 smoothed analog values using a multidimensional array from one master ESP32 to one slave ESP32. I am using the ESP-Now protocol.
Uber thanks to 6v6gt for help with multidimensional array.
For my modified code,
I was finally able to properly send each of the values on the transmitter side I believe based on my serial output. However, the transmitter serial output reports no peer found.
I'm still unclear about all of the ESP-Now terminology, but I thought I was sending the data variable appropriately.
Any help is appreciated. Since the modified code is too long I am creating separate posts for transmitter and receiver codes that are currently not working.
/* Free and open source, CC BY-SA 4.0 */
/*
ESPNOW - Basic communication - Master
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
Purpose: ESPNow Communication between a Master ESP32 and a Slave ESP32
Description: This sketch consists of the code for the Master module.
Resources: (A bit outdated)
a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
b. http://www.esploradores.com/practica-6-conexion-esp-now/
<< This Device Master >>
Flow: Master
Step 1 : ESPNow Init on Master and set it in STA mode
Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID of slave for an easy setup)
Step 3 : Once found, add Slave as peer
Step 4 : Register for send callback
Step 5 : Start Transmitting data from Master to Slave
Flow: Slave
Step 1 : ESPNow Init on Slave
Step 2 : Update the SSID of Slave with a prefix of `slave`
Step 3 : Set Slave in AP mode
Step 4 : Register for receive callback and wait for data
Step 5 : Once data arrives, print it in the serial monitor
Note: Master and Slave have been defined to easily understand the setup.
Based on the ESPNOW API, there is no concept of Master and Slave.
Any devices can act as master or slave.
*/
/*
Smoothing
Reads repeatedly from an analog input, calculating a running average and
printing it to the computer. Keeps xx readings in an array and continually
averages them.
created 22 Apr 2007
by David A. Mellis <dam@mellis.org>
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Smoothing
*/
//Libs for espnow and wifi
#include <esp_now.h>
#include <WiFi.h>
// Global copy of slave
esp_now_peer_info_t slave;
#define CHANNEL 3
#define PRINTSCANRESULTS 0
#define DELETEBEFOREPAIR 0
#include <driver/adc.h>
// Define the number of samples to keep track of. The higher the number, the
// more the readings will be smoothed, but the slower the output will respond to
// the input. Using a constant rather than a normal variable lets us use this
// value to determine the size of the readings array.
const int numReadings = 64;
const uint8_t numSensors = 2;
uint32_t readings[numSensors][numReadings]; //multi-dimensional readings from analog input
uint32_t total[numSensors] = {0}; // the running total
uint32_t readIndex = 0; // the index of the current reading
uint32_t average = 0; // the average
uint8_t EspNowAverage;
// delay to process smoothing readings
uint16_t numReadingsInterval = 1;
uint32_t lastEventAtMs = 0 ;
//Earth rotates .25 degrees/minute. In 4 minutes Earth rotates 1 degree.
uint8_t delay_ScanForSlave = 10; //Scan for slave delay time
void setup() {
//Set device in STA mode to begin with
Serial.begin(115200);
// initialize all the readings to 0:
for (uint16_t thisReading = 0; thisReading < numReadings; thisReading++) {
for ( int j = 0; j < numSensors; j++) readings[j][thisReading] = 0;
}
WiFi.mode(WIFI_STA);
Serial.println("ESPNow/Basic/Master Example");
// This is the mac address of the Master in Station Mode
Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());
// Init ESPNow with a fallback logic
InitESPNow();
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Transmitted packet
esp_now_register_send_cb(OnDataSent);
}
void loop() {
// Voltage divider analog in pins
// https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
// set up A:D channels
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //Pin34
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_CHANNEL_7, ADC_ATTEN_DB_11); //Pin35
// millis() -->Returns the number of milliseconds passed since the Arduino board began running the current program.
// This number will overflow (go back to zero), after approximately 50 days.
// timing resets to 0 when millis() - lastEventAtMS becomes greater than or equal to numReadingsInterval
// then loop proceeds with remaining functions
if ( millis() - lastEventAtMs >= numReadingsInterval ) {
lastEventAtMs = millis();
// Read the sensor
uint16_t Azimuth = adc1_get_raw(ADC1_CHANNEL_6);
uint16_t Elevation = adc1_get_raw(ADC1_CHANNEL_7);
uint16_t inputPin[ numSensors ] = {Azimuth, Elevation};
uint16_t ai;
for (ai = 0; ai < numSensors ; ai++) {
// subtract the last reading:
total[ ai ] = total[ ai ] - readings[ai][readIndex];
// read from the sensor:
readings[ai][readIndex] = inputPin[ai];
// add the reading to the total:
total[ai] = total[ai] + readings[ai][readIndex];
// calculate the average:
average = total[ai] / numReadings;
// reduce results to 0-255
EspNowAverage = average / 16; // send smoothed average of each sensor input to receiver
sendData();
}
// advance to the next position in the array:
readIndex = readIndex + 1;
// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
}
}
}
I'm suspecting that this line of code is limiting my ability to receive more data, but I am unsure:
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len)
My goal is to parse the two received analog inputs values on the slave side and then use each of the analog values to drive a total of two motors.
/* Free and open source, CC BY-SA 4.0 */
/*
ESPNOW - Basic communication - Slave
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
Purpose: ESPNow Communication between a Master ESP32 and a Slave ESP32
Description: This sketch consists of the code for the Slave module.
Resources: (A bit outdated)
a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
b. http://www.esploradores.com/practica-6-conexion-esp-now/
<< This Device Slave >>
Flow: Master
Step 1 : ESPNow Init on Master and set it in STA mode
Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID of slave for an easy setup)
Step 3 : Once found, add Slave as peer
Step 4 : Register for send callback
Step 5 : Start Transmitting data from Master to Slave
Flow: Slave
Step 1 : ESPNow Init on Slave
Step 2 : Update the SSID of Slave with a prefix of `slave`
Step 3 : Set Slave in AP mode
Step 4 : Register for receive callback and wait for data
Step 5 : Once data arrives, print it in the serial monitor
Note: Master and Slave have been defined to easily understand the setup.
Based on the ESPNOW API, there is no concept of Master and Slave.
Any devices can act as master or salve.
*/
#include <esp_now.h>
#include <WiFi.h>
#define CHANNEL 1
// Init ESP Now with fallback
void InitESPNow() {
WiFi.disconnect();
if (esp_now_init() == ESP_OK) {
Serial.println("ESPNow Init Success");
}
else {
Serial.println("ESPNow Init Failed");
// Retry InitESPNow, add a counte and then restart?
// InitESPNow();
// or Simply Restart
ESP.restart();
}
}
// config AP SSID
void configDeviceAP() {
char* SSID = "Slave_1";
bool result = WiFi.softAP(SSID, "Slave_1_Password", CHANNEL, 0);
if (!result) {
Serial.println("AP Config failed.");
} else {
Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID));
}
}
void setup() {
Serial.begin(115200);
Serial.println("ESPNow/Basic/Slave Example");
//Set device in AP mode to begin with
WiFi.mode(WIFI_AP);
// configure device AP mode
configDeviceAP();
// This is the mac address of the Slave in AP Mode
Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
// Init ESPNow with a fallback logic
InitESPNow();
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info.
esp_now_register_recv_cb(OnDataRecv);
}
// callback when data is recv from Master
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.print("Last Packet Recv from: "); Serial.println(macStr);
Serial.print("Last Packet Recv Data: "); Serial.println(*data);
Serial.println("");
}
void loop() {
// Chill
}
Although I don't have a lot of data. I'm sending two analog values with a range of 0-255, since the data variable is a uint8_t for the esp now protocol.
If there is a lot of ESP-NOW data to send, call esp_now_send() to send less than or equal to 250 bytes of data once a time. Note that too short interval between sending two ESP-NOW datas may lead to disorder of sending callback function. So, it is recommended that sending the next ESP-NOW data after the sending callback function of previous sending has returned. The sending callback function runs from a high-priority WiFi task. So, do not do lengthy operations in the callback function. Instead, post necessary data to a queue and handle it from a lower priority task.
FYI... the readings I'm taking have an interval of 1 ms. A total of 64 readings occur so there should be at least a 64 ms interval before the next reading is sent. Correct? Wouldn't this be good enough for requirement mentioned above? I don't know how else to delay the sending of void loop code. My previous attempts of using millis() to delay loop were not good since someone mentioned I was using blocking code.
Were you ever able to send and receive an array of values using ESP-NOW? I've seen code online that seems to imply that it's possible, but I haven't yet been able to make it actually work.
The code is in post numbers 2 and 3.
It was probably too long for most people to go over.
I was getting data on the receiver side but still have to work on familiarizing myself better with arrays.
I don't think I was properly splitting or assigning array values on the slave end code based on the motor output results I was getting.
I was covering up my sensors with my fingers to get the proper data output from the sensors but the proper data was not showing up on the receiver side. I think it was only receiving data from 1 or 2 sensors rather than all 4.
Ok. I'm taking a look at the thread right now. Since the code is for the ESP8266 it's a little bit different for the ESP32 I believe.
I've attached my files since the code in them is too long.
I was able to successfully transmit the array values, but I think I need to send them as an array and receive them properly on the receiver side.
I believe if I understood it correctly I need to add another layer in the multidimensional array.
Don't know if that's the right terminology for it.
I may need to nest it one more time.
Serial output of master before slave is powered and uploaded with receiver code:
Fail
33
22
Fail
Fail
35
23
Serial output of master after slave is powered and uploaded with receiver code:
Serial output of slave with succesfull tranmission of data:
121
100
AZIMUTH MOTOR MOVES COUNTERCLOCKWISE
ELEVATION MOTOR MOVES COUNTERCLOCKWISE
118
97
AZIMUTH MOTOR MOVES COUNTERCLOCKWISE
ELEVATION MOTOR MOVES COUNTERCLOCKWISE
115
95
AZIMUTH MOTOR MOVES COUNTERCLOCKWISE
ELEVATION MOTOR MOVES COUNTERCLOCKWISE
113
92
AZIMUTH MOTOR MOVES COUNTERCLOCKWISE
ELEVATION MOTOR MOVES COUNTERCLOCKWISE
The problem I have is that on the receiver side I don't know how to assign the data variable the proper array values that are being received. I believe that is the reason why the motors will only spin counterclockwise.
I tried to follow the example of the code in this instructables tutorial (he has an array of digital on/off values I believe), his website code is more uniform and joined together. His instructable code is a bit incomplete I believe. His video is in Portugese so that makes it more harder to understand.