Send analog values using espnow

knightridar
Posts: 32
Joined: Sun Nov 25, 2018 10:05 pm
Contact:

Send analog values using espnow

Postby knightridar » Mon Nov 26, 2018 12:51 am

Is there sample code anywhere to send analog values between two esp32s using the espnow function?
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

chegewara
Posts: 2207
Joined: Wed Jun 14, 2017 9:00 pm

Re: Send analog values using espnow

Postby chegewara » Mon Nov 26, 2018 6:10 am

The code is not different than sending integer value or string. Its at all just a bunch of bytes.

knightridar
Posts: 32
Joined: Sun Nov 25, 2018 10:05 pm
Contact:

Re: Send analog values using espnow

Postby knightridar » Mon Nov 26, 2018 7:00 am

Hi I used this website:
https://www.instructables.com/id/ESP32- ... -Protocol/

His code is not complete on instructables but it seems to be complete on his website:
https://www.fernandok.com/2018/03/esp32 ... p-now.html

I'm not using pushbuttons like him to active the led on the esp32.
I'm using 4 photoresistors, but my array is not transferring those values to the slave.
I'm not getting anything on my serial output on the slave side.

I tried to change this to:
analogWrite below on the slave side but I got an error.
Any thoughts? Thanks.

Code: Select all

   //Sets its output to match the received value
    digitalWrite(gpios[i], data[i]);
Master side:

Code: Select all

//allows you to communicate with I2C
#include<Wire.h>

//Libs for espnow and wifi
#include <esp_now.h>
#include <WiFi.h>

//Channel used in the connection
#define CHANNEL 1

const int MPU_addr = 0x68;
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

int minVal = 85;
int maxVal = 402;

double x;
int EA; //elevation angle
double z;

//top left sensor pin = PinTL
const int PinTL = 33;
const int PinBL = 35;
const int PinTR = 32;
const int PinBRT = 34;

// The sensor value
int TL = 0;
int BL = 0;
int TR = 0;
int BRT = 0;

// As photoresistor approaches minimum sensor value more light is seen by it
int MinTL = 0;
int MinBL = 0;
int MinTR = 0;
int MinBRT = 0;

int MaxTL = 4096;
int MaxBL = 4096;
int MaxTR = 4096;
int MaxBRT = 4096;

//Gpios that we are going to read (analogRead) and send to the Slaves
//It's important that the Slave source code has this same array
//with the same gpios in the same order
uint8_t gpios[] = {TL,BL,TR,BRT};

//In the setup function we'll calculate the gpio count and put in this variable,
//so we don't need to change this variable everytime we change
//the gpios array total size, everything will be calculated automatically
//on setup function
int gpioCount;

//Slaves Mac Addresses that will receive data from the Master
//If you want to send data to all Slaves, use only the broadcast address {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
//If you want to send data to specific Slaves, put their Mac Addresses separeted with comma (use WiFi.macAddress())
//to find out the Mac Address of the ESPs while in STATION MODE)
uint8_t macSlaves[][6] = {
  //To send to specific Slaves
  //{0x24, 0x0A, 0xC4, 0x0E, 0x3F, 0xD1}, {0x24, 0x0A, 0xC4, 0x0E, 0x4E, 0xC3}
  //Or to send to all Slaves
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
};

void setup() {
  
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  
  Serial.begin(115200);

  //Calculation of gpio array size:
  //sizeof(gpios) returns how many bytes "gpios" array points to.
  //Elements in this array are of type uint8_t.
  //sizeof(uint8_t) return how many bytes uint8_t type has.
  //Therefore if we want to know how many gpios there are,
  //we divide the total byte count of the array by how many bytes
  //each element has.
  gpioCount = sizeof(gpios)/sizeof(uint8_t);

  //Puts ESP in STATION MODE
  WiFi.mode(WIFI_STA);

  //Shows on the Serial Monitor the STATION MODE Mac Address of this ESP
  Serial.print("Mac Address in Station: "); 
  Serial.println(WiFi.macAddress());

  //Calls the function that will initialize the ESP-NOW protocol
  InitESPNow();

//Calculation of the size of the slaves array:
  //sizeof(macSlaves) returns how many bytes the macSlaves array points to.
  //Each Slave Mac Address is an array with 6 elements.
  //If each element is sizeof(uint8_t) bytes
  //then the total of slaves is the division of the total amount of bytes
  //by how many elements each MAc Address has
  //by how much bytes each element has.
  int slavesCount = sizeof(macSlaves)/6/sizeof(uint8_t);

  //For each Slave
  for(int i=0; i<slavesCount; i++){
  //We create a variable that will store the slave information
  esp_now_peer_info_t slave;
  //We inform the channel
  slave.channel = CHANNEL;
  //0 not to use encryption or 1 to use
  slave.encrypt = 0;
  //Copies the array address to the structure
  memcpy(slave.peer_addr, macSlaves[i], sizeof(macSlaves[i]));
  //Add the slave
  esp_now_add_peer(&slave);
}

  //Registers the callback that will give us feedback about the sent data
  //The function that will be executed is called OnDataSent
  esp_now_register_send_cb(OnDataSent);
  
  //For each gpio
   //For each GPIO pin in array
  for(int i=0; i<gpioCount; i++){
    //We put in read mode
    pinMode(gpios[i], INPUT);
  }
 
  //Calls the send function
  send();
}

void InitESPNow() {
  //If the initialization was successful
  if (esp_now_init() == ESP_OK) {
    Serial.println("ESPNow Init Success");
  }
  //If there was an error
  else {
    Serial.println("ESPNow Init Failed");
    ESP.restart();
  }
}

//Function that will read the gpios and send
//the read values to the others ESPs
void send(){
  //Array that will store the read values
  uint8_t values[gpioCount];

  //For each gpio
  for(int i=0; i<gpioCount; i++){

    //Reads the value (HIGH or LOW) of the gpio
    //and stores the value on the array
    values[i] = analogRead(gpios[i]);
  }

  //In this example we are going to use the broadcast address {0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF}
  //to send the values to all Slaves.
  //If you want to send to a specific Slave, you have to put its Mac Address on macAddr.
  //If you want to send to more then one specific Slave you will need to create
  //a "for loop" and call esp_now_send for each mac address on the macSlaves array
  uint8_t macAddr[] = {0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF};
  esp_err_t result = esp_now_send(macAddr, (uint8_t*) &values, sizeof(values));
  Serial.print("Send Status: ");
  //If it was successful
  if (result == ESP_OK) {
    Serial.println("Success");
  }
  //if it failed
  else {
    Serial.println("Error");
  }
}

//Callback function that gives us feedback about the sent data
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  char macStr[18];
  //Copies the receiver Mac Address to a string
  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]);
  //Prints it on Serial Monitor
  Serial.print("Sent to: "); 
  Serial.println(macStr);
  //Prints if it was successful or not
  Serial.print("Status: "); 
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
  //Sends again
  send();
}

//We don't do anything on the loop.
//Every time we receive feedback about the last sent data,
//we'll be calling the send function again,
//therefore the data is always being sent

void loop() {

   Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr, 14, true);

  AcX = Wire.read() << 8 | Wire.read();
  AcY = Wire.read() << 8 | Wire.read();
  AcZ = Wire.read() << 8 | Wire.read();

  int xAng = map(AcX, minVal, maxVal, -180, 180);
  int yAng = map(AcY, minVal, maxVal, -180, 180);
  int zAng = map(AcZ, minVal, maxVal, -180, 180);

  EA = RAD_TO_DEG * (atan2(xAng, zAng));

  // Calibrate during the first five seconds
  while (millis() < 5000) {
    TL = analogRead(PinTL);
    BL = analogRead(PinBL);
    TR = analogRead(PinTR);
    BRT = analogRead(PinBRT);

    // Record the maximum sensor value
    if (TL > MaxTL) {
      MaxTL = TL;
    }
    if (BL > MaxBL) {
      MaxBL = BL;
    }
    if (TR > MaxTR) {
      MaxTR = TR;
    }
    if (BRT > MaxBRT) {
      MaxBRT = BRT;
    }

    if (TL < MinTL) {
      MinTL = TL;
    }
    if (BL < MinBL) {
      MinBL = BL;
    }
    if (TR < MinTR) {
      MinTR = TR;
    }
    if (BRT < MinBRT) {
      MinBRT = BRT;
    }
  }
  // Signal the end of the calibration period

  // Read the sensor
  TL = analogRead(PinTL); // Top left sensor
  BL = analogRead(PinBL); // Bottom left sensor
  TR = analogRead(PinTR); // Top right sensor
  BRT = analogRead(PinBRT); // Bottom right sensor

  // Apply the calibration to the sensor reading
  TL = map(TL, MinTL, MaxTL, 0, 1023);
  BL = map(BL, MinBL, MaxBL, 0, 1023);
  TR = map(TR, MinTR, MaxTR, 0, 1023);
  BRT = map(BRT, MinBRT, MaxBRT, 0, 1023);

  // In case the sensor value is outside the range seen during calibration
  TL = constrain(TL, 0, 1023);
  BL = constrain(BL, 0, 1023);
  TR = constrain(TR, 0, 1023);
  BRT = constrain(BRT, 0, 1023);

  //Sends analog values in this format: i.e. <380,148,224,260,45>
  Serial.print("<");
  Serial.print(TL);
  Serial.print(",");
  Serial.print(BL);
  Serial.print(",");
  Serial.print(TR);
  Serial.print(",");
  Serial.print(BRT);
  Serial.print(",");
  Serial.print(EA);
  Serial.print(">");

  Serial.println();

  delay(5000);
 }
Slave side:

Code: Select all

//Libs for espnow e wifi
#include <esp_now.h>
#include <WiFi.h>
 

//Gpios we'll write the values received from the Master
//It's important that the Master source code has this same array
//with the same gpios in the same order
uint8_t gpios[] = {33,35,32,34};

//In the setup function we'll calculate the gpio count and put in this variable,
//so we don't need to change this variable everytime we change
//the gpios array total size, everything will be calculated automatically
//on setup function
int gpioCount;

void setup() {
  Serial.begin(115200);
  
  //Calculation of gpio array size:
  //sizeof(gpios) returns how many bytes "gpios" array points to.
  //Elements in this array are of type uint8_t.
  //sizeof(uint8_t) return how many bytes uint8_t type has.
  //Therefore if we want to know how many gpios there are,
  //we divide the total byte count of the array by how many bytes
  //each element has.
  gpioCount = sizeof(gpios)/sizeof(uint8_t);

  //Puts ESP in STATION MODE
  WiFi.mode(WIFI_STA);

  //Shows on the Serial Monitor the STATION MODE Mac Address of this ESP
  Serial.print("Mac Address in Station: "); 
  Serial.println(WiFi.macAddress());

  //Calls the function that will initialize the ESP-NOW protocol
  InitESPNow();

  //Registers the callback function that will be executed when 
  //this Slave receives data from the Master.
  //The function in this case is called OnDataRecv
  esp_now_register_recv_cb(OnDataRecv);

  //For each gpio on gpios array
   for(int i=0; i<gpioCount; i++){
    //We put in read mode
    pinMode(gpios[i], OUTPUT);
  }
}


  void InitESPNow() {
  //If the initialization was successful
  if (esp_now_init() == ESP_OK) {
    Serial.println("ESPNow Init Success");
  }
  //If there was an error
  else {
    Serial.println("ESPNow Init Failed");
    ESP.restart();
  }
}

//Callback function that tells us when data from Master is received
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
  char macStr[18];
  //Copies the sender Mac Address to a string
  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]);
  //Prints it on Serial Monitor
  Serial.print("Received from: "); 
  Serial.println(macStr);
  Serial.println("");

  //For each gpio
  for(int i=0; i<gpioCount; i++){

    //Sets its output to match the received value
    digitalWrite(gpios[i], data[i]);
  }
}

//We don't do anything on the loop.
//Everytime something comes from Master
//the OnDataRecv function is executed automatically
//because we added it as callback using esp_now_register_recv_cb
void loop() {}
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

chegewara
Posts: 2207
Joined: Wed Jun 14, 2017 9:00 pm

Re: Send analog values using espnow

Postby chegewara » Mon Nov 26, 2018 11:57 pm

Couple thoughts:
https://github.com/espressif/arduino-esp32
Most of the framework is implemented. Most noticable is the missing analogWrite. While analogWrite is on it's way, there are a few other options that you can use:

- 16 channels LEDC which is PWM
- 8 channels SigmaDelta which uses SigmaDelta modulation
- 2 channels DAC which gives real analog output

Some pins you are using as output are input only.

knightridar
Posts: 32
Joined: Sun Nov 25, 2018 10:05 pm
Contact:

Re: Send analog values using espnow

Postby knightridar » Sun Dec 02, 2018 7:31 am

hi I am using this library example on git hub

ESPNow Master
https://github.com/espressif/arduino-es ... Master.ino

ESPNow Slave
https://github.com/espressif/arduino-es ... /Slave.ino

For the master code i'm trying to send these values in the void sendData() function, but they are not transmitting successfully to the slave side can you please advise?:

Code: Select all

uint8_t data = 0;
// send data
void sendData() {
  //Sends analog values in this format: i.e. <380,148,224,260,45>
  Serial.print("<");
  Serial.print(TL);
  Serial.print(",");
  Serial.print(BL);
  Serial.print(",");
  Serial.print(TR);
  Serial.print(",");
  Serial.print(BRT);
  Serial.print(",");
  Serial.print(EA);
  Serial.print(">");
  Serial.println();

  data++;
  const uint8_t *peer_addr = slave.peer_addr;
  Serial.print("Sending: "); Serial.println(data);
  esp_err_t result = esp_now_send(peer_addr, &data, sizeof(data));
  Serial.print("Send Status: ");
  if (result == ESP_OK) {
    Serial.println("Success");
  } else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
    // How did we get so far!!
    Serial.println("ESPNOW not Init.");
  } else if (result == ESP_ERR_ESPNOW_ARG) {
    Serial.println("Invalid Argument");
  } else if (result == ESP_ERR_ESPNOW_INTERNAL) {
    Serial.println("Internal Error");
  } else if (result == ESP_ERR_ESPNOW_NO_MEM) {
    Serial.println("ESP_ERR_ESPNOW_NO_MEM");
  } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
    Serial.println("Peer not found.");
  } else {
    Serial.println("Not sure what happened");
  }
}
MASTER SERIAL RESULTS:

Code: Select all

Found 12 devices 
Found a Slave.
1: Slave_1 [30:AE:A4:F3:14:95] (-49)
Slave Found, processing..
Slave Status: Already Paired
<49,59,97,91,-135>
Sending: 2
Send Status: Success
Last Packet Sent to: 30:ae:a4:f3:14:95
Last Packet Send Status: Delivery Success
SLAVE SERIAL RESULTS:

Code: Select all

Last Packet Recv from: 30:ae:a4:ef:bf:1c
Last Packet Recv Data: 103
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

knightridar
Posts: 32
Joined: Sun Nov 25, 2018 10:05 pm
Contact:

Re: Send analog values using espnow

Postby knightridar » Tue Mar 19, 2019 4:59 am

I'm going to try to send 4 analog values (from photoresistors) and one i2c value (accelerometer measuring angle) and put these all in an int array.

This is different than what I was trying before. Can someone advise how I can send it using the espnow master example and receive it in the espnow receive example mentioned in previous posts.

I see the int data=0 variable, and how it sends data.
But get confused with the rest of the syntax in the void send and void recv functions.

Can someone please give an example?

Thanks.
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

knightridar
Posts: 32
Joined: Sun Nov 25, 2018 10:05 pm
Contact:

Re: Send analog values using espnow

Postby knightridar » Tue Apr 09, 2019 8:18 am

I've been able to make some progress in putting in the analog values on the transmitter side,
but on the receiver side I'm still not receiving the data.
I did map my 12 bit analog values but they are not uint8_t since they are bigger than 255.
They are mapped to 0-3300 mV because my analog inputs are being read via a voltage divider.

Code: Select all

/*
   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 ten 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;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
long total = 0;                  // the running total
long average = 0;                // the average

unsigned long delay_time = 5000;  //Earth rotates .25 degrees/minute. In 4 minutes Earth rotates 1 degree.
unsigned long time_now = 0;

int Azimuth = 0;
int Elevation = 0;

int AzimuthVoltage = 0;
int ElevationVoltage = 0;

/***************************Void functions**********************************/

// 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();
  }
}

// Scan for slaves in AP mode
void ScanForSlave() {
  int8_t scanResults = WiFi.scanNetworks();
  // reset on each scan
  bool slaveFound = 0;
  memset(&slave, 0, sizeof(slave));

  Serial.println("");
  if (scanResults == 0) {
    Serial.println("No WiFi devices in AP Mode found");
  } else {
    Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
    for (int i = 0; i < scanResults; ++i) {
      // Print SSID and RSSI for each device found
      String SSID = WiFi.SSID(i);
      int32_t RSSI = WiFi.RSSI(i);
      String BSSIDstr = WiFi.BSSIDstr(i);

      if (PRINTSCANRESULTS) {
        Serial.print(i + 1);
        Serial.print(": ");
        Serial.print(SSID);
        Serial.print(" (");
        Serial.print(RSSI);
        Serial.print(")");
        Serial.println("");
      }
      delay(10);
      // Check if the current device starts with `Slave`
      if (SSID.indexOf("Slave") == 0) {
        // SSID of interest
        Serial.println("Found a Slave.");
        Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println("");
        // Get BSSID => Mac Address of the Slave
        int mac[6];
        if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c",  &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
          for (int ii = 0; ii < 6; ++ii ) {
            slave.peer_addr[ii] = (uint8_t) mac[ii];
          }
        }

        slave.channel = CHANNEL; // pick a channel
        slave.encrypt = 0; // no encryption

        slaveFound = 1;
        // we are planning to have only one slave in this example;
        // Hence, break after we find one, to be a bit efficient
        break;
      }
    }
  }

  if (slaveFound) {
    Serial.println("Slave Found, processing..");
  } else {
    Serial.println("Slave Not Found, trying again.");
  }

  // clean up ram
  WiFi.scanDelete();
}

// Check if the slave is already paired with the master.
// If not, pair the slave with master
bool manageSlave() {
  if (slave.channel == CHANNEL) {
    if (DELETEBEFOREPAIR) {
      deletePeer();
    }

    Serial.print("Slave Status: ");
    const esp_now_peer_info_t *peer = &slave;
    const uint8_t *peer_addr = slave.peer_addr;
    // check if the peer exists
    bool exists = esp_now_is_peer_exist(peer_addr);
    if ( exists) {
      // Slave already paired.
      Serial.println("Already Paired");
      return true;
    } else {
      // Slave not paired, attempt pair
      esp_err_t addStatus = esp_now_add_peer(peer);
      if (addStatus == ESP_OK) {
        // Pair success
        Serial.println("Pair success");
        return true;
      } else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) {
        // How did we get so far!!
        Serial.println("ESPNOW Not Init");
        return false;
      } else if (addStatus == ESP_ERR_ESPNOW_ARG) {
        Serial.println("Invalid Argument");
        return false;
      } else if (addStatus == ESP_ERR_ESPNOW_FULL) {
        Serial.println("Peer list full");
        return false;
      } else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) {
        Serial.println("Out of memory");
        return false;
      } else if (addStatus == ESP_ERR_ESPNOW_EXIST) {
        Serial.println("Peer Exists");
        return true;
      } else {
        Serial.println("Not sure what happened");
        return false;
      }
    }
  } else {
    // No slave found to process
    Serial.println("No Slave found to process");
    return false;
  }
}

void deletePeer() {
  const esp_now_peer_info_t *peer = &slave;
  const uint8_t *peer_addr = slave.peer_addr;
  esp_err_t delStatus = esp_now_del_peer(peer_addr);
  Serial.print("Slave Delete Status: ");
  if (delStatus == ESP_OK) {
    // Delete success
    Serial.println("Success");
  } else if (delStatus == ESP_ERR_ESPNOW_NOT_INIT) {
    // How did we get so far!!
    Serial.println("ESPNOW Not Init");
  } else if (delStatus == ESP_ERR_ESPNOW_ARG) {
    Serial.println("Invalid Argument");
  } else if (delStatus == ESP_ERR_ESPNOW_NOT_FOUND) {
    Serial.println("Peer not found.");
  } else {
    Serial.println("Not sure what happened");
  }
}

uint8_t data = 0;
// send data
void sendData() {
  time_now = millis();
  data++;
  const uint8_t *peer_addr = slave.peer_addr;
  Serial.print("Sending: "); Serial.println(data);
  esp_err_t result = esp_now_send(peer_addr, &data, sizeof(data));
  Serial.print("Send Status: ");
  if (result == ESP_OK) {
    Serial.println("Success");
  } else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
    // How did we get so far!!
    Serial.println("ESPNOW not Init.");
  } else if (result == ESP_ERR_ESPNOW_ARG) {
    Serial.println("Invalid Argument");
  } else if (result == ESP_ERR_ESPNOW_INTERNAL) {
    Serial.println("Internal Error");
  } else if (result == ESP_ERR_ESPNOW_NO_MEM) {
    Serial.println("ESP_ERR_ESPNOW_NO_MEM");
  } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
    Serial.println("Peer not found.");
  } else {
    Serial.println("Not sure what happened");
  }

  //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

  // Read the sensor
  Azimuth =  adc1_get_raw(ADC1_CHANNEL_7);
  Elevation = adc1_get_raw(ADC1_CHANNEL_6);

  int inputPin[2] = {Azimuth, Elevation};

  uint8_t ai;

  for (ai = 0; ai < 2; ai++) {
    // subtract the last reading:
    total = total - readings[readIndex];
    // read from the sensor:
    readings[readIndex] = inputPin[ai];
    // add the reading to the total:
    total = total + readings[readIndex];
    // 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;
    }
    // calculate the average:
    average = total / numReadings;
    // send it to the computer as ASCII digits
  }

  // Apply the calibration to the sensor reading
  AzimuthVoltage = map(Azimuth, 0, 4096, 0, 3300);
  ElevationVoltage = map(Elevation, 0, 4096, 0, 3300);

  //Sends analog values in this format: i.e. {1800,2100}
  int data[2] = {AzimuthVoltage, ElevationVoltage};
  uint8_t i;

  Serial.println(" ");

  for (i = 0; i < 2; i++) {
    Serial.print(data[i]);
    Serial.println(" ");
  }
  Serial.println(" ");

  //wait approx. [period] ms}
  while (millis() < time_now + delay_time) {}
}

// callback when data is sent from Master to Slave
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  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 Sent to: "); Serial.println(macStr);
  Serial.print("Last Packet Send Status: "); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

/***************************End of Void functions**********************************/

void setup() {

  //Set device in STA mode to begin with
  Serial.begin(115200);

  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[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() {

  // In the loop we scan for slave
  ScanForSlave();
  // If Slave is found, it would be populate in `slave` variable
  // We will check if `slave` is defined and then we proceed further
  if (slave.channel == CHANNEL) { // check if slave channel is defined
    // `slave` is defined
    // Add slave as peer if it has not been added already
    bool isPaired = manageSlave();
    if (isPaired) {
      // pair success or already paired
      // Send data to device
      sendData();
    } else {
      // slave pair failed
      Serial.println("Slave pair failed!");
    }
  }
  else {
    // No slave found to process
  }
}
For the receiver side I'm using the code that is on the github site for esp now slave.
Am I missing something?

Code: Select all

/*
   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);
}

void loop() {
  // Chill
}
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

ShadowJ14
Posts: 2
Joined: Thu Oct 31, 2019 8:09 pm

Re: Send analog values using espnow

Postby ShadowJ14 » Thu Oct 31, 2019 8:18 pm

Hello knightridar,

The last post on this thread has been quite a while ago and I wish I could help you but I'm getting started on microcontrollers programing and Esp_now and I was looking to send analog values as well, from an analog stick and a potentiometer and I was reading your post and saw you were having some progress and would love to know if you did manage to do it. I wanted to ask you as well if you tried converting the numbers from the voltage to under 255 (dividing by a constant) so you could use uint8_t. I'll keep my fingers crossed for a reply :P

knightridar
Posts: 32
Joined: Sun Nov 25, 2018 10:05 pm
Contact:

Re: Send analog values using espnow

Postby knightridar » Fri Nov 08, 2019 5:44 am

Hi this is the closest I've gotten so far:

https://esp32.com/viewtopic.php?f=19&t=13054

I have another example too that I'll look for but had trouble assigning it on receiving side.
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

ShadowJ14
Posts: 2
Joined: Thu Oct 31, 2019 8:09 pm

Re: Send analog values using espnow

Postby ShadowJ14 » Tue Dec 10, 2019 2:54 am

Hello knightridar,

I would like to let you know that I was able to make what I meant to do work. I checked the link you provided and there are a lot of things I don't fully grasp yet. I dunno if it will help you or not but I'm gonna share you how I did (could be a noob way to go about it but if it works it works :p)

Master code

Code: Select all

//#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>
#include "heltec.h"
#include <esp_wifi_internal.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>


#define CHANNEL 1
#define DATARATE WIFI_PHY_RATE_24M
#define PRINTSCANRESULTS 0
#define DELETEBEFOREPAIR 0

//#define RST_OLED 16                     //OLED Reset引脚,需要手动Reset,否则不显示
#define OLED_UPDATE_INTERVAL 500        //OLED屏幕刷新间隔ms
//SSD1306 display(0x3C, 4, 15);

//dados de autenticação
const char* ssid = "";
const char* password = "";

//esp_now_peer_info_t slave;

char* readController();

//int But0, But1, But2, But3, But4, But5, But6, But7, But8, But9, But10, But11, joyXL, joyYL, joyXR, joyYR;
//SSD1306  display(0x3c, 21, 22);

int butSpeed = 0;

//pino do potenciometro
int potPin1 = 22;

//ADC max on ESP32 (12bit ADC width)
int ADC_Max = 4095;


//Pinos que iremos ler (digitalRead) e enviar para os Slaves
//É importante que o código fonte dos Slaves tenha este mesmo array com os mesmos gpios
//na mesma ordem

uint8_t gpios[] = {2, 22, 23, 17, 12, 25, 39, 38, 37, 36, 13};

  

//No setup iremos calcular a quantidade de pinos e colocar nesta variável,
//assim não precisamos trocar aqui toda vez que mudarmos a quantidade de pinos,
//tudo é calculado no setup
int gpioCount;

//Mac Address dos slaves para os quais iremos enviar a leitura
//Se quiser enviar para todos os Slaves utilize apenas o endereço de broadcast {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}.
//Se quiser enviar para ESPs específicos coloque o Mac Address (obtido através da função WiFi.macAddress())
uint8_t macSlaves[][6] = {
  //Se for enviar para ESPs específicos, coloque cada endereço separado por vírgula
  // {0x24, 0x0A, 0xC4, 0x0E, 0x3F, 0xD1}, {0x24, 0x0A, 0xC4, 0x0E, 0x4E, 0xC3}
  //Se for enviar para todos, apenas deixe o endereço de broadcast {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
};


void setup() {
  


  Serial.begin(115200);

  Heltec.begin(true, false, true);

  
  Heltec.display->flipScreenVertically();
  Heltec.display->setFont(ArialMT_Plain_10);



  //Cálculo do tamanho do array de gpios que serão lidos com o digitalRead
  //sizeof(gpios) retorna a quantidade de bytes que o array gpios aponta
  //Sabemos que todos os elementos do array são do tipo uint8_t
  //sizeof(uint8_t) retorna a quantidade de bytes que o tipo uint8_t possui
  //Sendo assim para saber quantos elementos o array possui
  //fazemos a divisão entre a quantidade total de bytes do array e quantos
  //bytes cada elemento possui
  gpioCount = sizeof(gpios) / sizeof(uint8_t);

  //Coloca o ESP em modo station
  WiFi.mode(WIFI_STA);

  //Desligar o WiFi para iniciar ESPNow
  WiFi.disconnect();
  //Chama a função que inicializa o ESPNow
  InitESPNow();

//Cálculo do tamanho do array com os mac address dos slaves
//sizeof(macSlaves) retorna a quantidade de bytes que o array macSlaves aponta
//Sabemos que cada mac address é um array de 6 posições e
//cada posição possui sizeof(uint8_t) bytes, então
//a quantidade de slaves é a divisão da quantidade de bytes
//total do array pela quantidade de posições e o resultado
//dessa divisão dividimos novamente por quantos bytes cada posição possui
  int slavesCount = sizeof(macSlaves) / 6 / sizeof(uint8_t);
//Para cada slave
  for (int i = 0; i < slavesCount; i++) {
  //Criamos uma variável que irá guardar as informações do slave
    esp_now_peer_info_t slave;
  //Informamos o canal
    slave.channel = CHANNEL;
  //0 para não usar criptografia ou 1 para usar
    slave.encrypt = 0;
  //Copia o endereço do array para a estrutura
    memcpy(slave.peer_addr, macSlaves[i], sizeof(macSlaves[i]));
  //Adiciona o slave
    esp_now_add_peer(&slave);
  }
  
//Registra o callback que nos informará sobre o status do envio
  //A função que será executada é OnDataSent e está declarada mais abaixo
  esp_now_register_send_cb(OnDataSent);
//Para cada pino que está no array gpios (estava gpioCount em vez do numero 9)
  for (int i=0; i < gpioCount; i++){ 
//Colocamos em modo input até ao analógico
    pinMode(gpios[i], INPUT);
  }
  //Chama a função send
  send();
}

  void InitESPNow() {
  //Se a inicialização foi bem sucedida
  if (esp_now_init() == ESP_OK) {
    Serial.println("ESPNow Init Success");
  }
  //Se houve erro na inicialização
  else {
    Serial.println("ESPNow Init Failed");
    ESP.restart();
  }
}

//Função que irá fazer a leitura dos pinos
//que estão no array gpios e enviar os valores
//lidos para os outros ESPs

void displayshow(){

  Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT);
  Heltec.display->setColor(WHITE);
  //Heltec.display->clear();
  Heltec.display->drawString(0, 0, "BangBang\nController\nwith\nESP-NOW");

}

void send(){

 valPot1 = analogRead(potPin1);
 valPot1 = map(valPot1, 0, ADC_Max, 0, 180);

 Serial.println(valPot1);

  
  //Array que irá armazenar os valores lidos
  uint8_t values[gpioCount];
 
  //Para cada pino
  for(int i=0; i < gpioCount; i++){
    //Lê o estado do pino e armazena no array
    values[i] = digitalRead(gpios[i]);
    values[1] = valPot1;

    Serial.println("gpios");
    Serial.println(gpios[i]);
    Serial.println("values");
    Serial.println(values[i]);
  }

  //O endereço de broadcast irá enviar as informações para todos os ESPs
  //Se quiser que a informação vá para ESPs específicos você deve chamar a função
  //esp_now_send para cada Mac Address, passando o Mac Address como primeiro
  //parâmetro no lugar do broadcast
  uint8_t broadcast[] = {0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF};
  esp_err_t result = esp_now_send(broadcast, (uint8_t*) &values, sizeof(values));
  Serial.print("Send Status: ");
  //Se o envio foi bem sucedido
  if (result == ESP_OK) {
    Serial.println("Success");
  }
  //Se aconteceu algum erro no envio
  else {
    Serial.println("Error");
  }
}

//Função que serve de callback para nos avisar
//sobre a situação do envio que fizemos
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  char macStr[18];
  //Copiamos o Mac Address destino para uma string
  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]);
  //Mostramos o Mac Address que foi destino da mensagem
  Serial.print("Sent to: "); 
  Serial.println(macStr);
  //Mostramos se o status do envio foi bem sucedido ou não
  Serial.print("Status: "); 
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
  //Enviamos novamente os dados
  send();
}

  void loop() {

    Heltec.display->clear();
    Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT);
    Heltec.display->setFont(ArialMT_Plain_10);
    Heltec.display->drawString(0, 0, "pin:" + String(gpios[1]));
    Heltec.display->setFont(ArialMT_Plain_10);
    Heltec.display->drawString(0, 10, "valor:" + String(values[1]));
    Heltec.display->display();
    delay(10);
    Heltec.display->clear();
    Heltec.display->display();
    //delay(100);
}
Slave code

Code: Select all

#include <ESP32Servo.h>
#include <esp_now.h>
#include <WiFi.h>

#define CHANNEL 1
#define DATARATE WIFI_PHY_RATE_24M
#define PRINTSCANRESULTS 0
#define DELETEBEFOREPAIR 0

#define OLED_UPDATE_INTERVAL 500

Servo myservo;  // create servo object to control a servo

//dados de autenticação
const char* ssid = "";
const char* password = "";

//Pinos que iremos escrever (digitalWrite) cujos valores são recebios do Master
//É importante que o código fonte do Master tenha este mesmo array com os mesmos gpios
//na mesma ordem
uint8_t gpios[] = {2, 22, 23, 17, 12, 25, 39, 38, 37, 36, 13};

//No setup iremos calcular a quantidade de pinos e colocar nesta variável,
//assim não precisamos trocar aqui toda vez que mudarmos a quantidade de pinos,
//tudo é calculado no setup
int gpioCount;

// Possible PWM GPIO pins on the ESP32: 0(used by on-board button),2,4,5(used by on-board LED),12-19,21-23,25-27,32-33 
int servoPin = gpios[0];      // GPIO pin used to connect the servo control (digital out)

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

  //Cálculo do tamanho do array de gpios
  //sizeof(gpios) retorna a quantidade de bytes que o array gpios aponta
  //Sabemos que todos os elementos do array são do tipo uint8_t
  //sizeof(uint8_t) retorna a quantidade de bytes que o tipo uint8_t possui
  //Sendo assim para saber quantos elementos o array possui
  //fazemos a divisão entre a quantidade total de bytes do array e quantos
  //bytes cada elemento possui
  gpioCount = sizeof(gpios)/sizeof(uint8_t);

  //Colocamos o ESP em modo station
  WiFi.mode(WIFI_STA);

  //Mostramos no Monitor Serial o Mac Address deste ESP quando em modo station
  //Se quiser que o Master mande para ESPs em específico, altere no 
  //array de slaves (no código fonte do Master) para que ele possua apenas os Mac Addresses printados aqui
  Serial.print("Mac Address in Station: "); 
  Serial.println(WiFi.macAddress());

  //Chama a função que inicializa o ESPNow
  InitESPNow();

    //Registra o callback que nos informará quando o Master enviou algo
  //A função que será executada é OnDataRecv e está declarada mais abaixo
  esp_now_register_recv_cb(OnDataRecv);
  //Para cada pino que está no array gpios (estava gpioCount em vez do numero 9)
  for (int i=0; i<gpioCount; i++){ 
//Colocamos em modo input até ao analógico
    pinMode(gpios[i], OUTPUT);
  }
  
  myservo.setPeriodHertz(50);// Standard 50hz servo
  myservo.attach(servoPin, 500, 2400);   // attaches the servo on pin 18 to the servo object
                                         // using SG90 servo min/max of 500us and 2400us
                                         // for MG995 large servo, use 1000us and 2000us,
                                         // which are the defaults, so this line could be
                                         // "myservo.attach(servoPin);"
}

void InitESPNow() {
  //Se a inicialização foi bem sucedida
  if (esp_now_init() == ESP_OK) {
    Serial.println("ESPNow Init Success");
  }
  //Se houve erro na inicialização
  else {
    Serial.println("ESPNow Init Failed");
    ESP.restart();
  }
}

//Função que serve de callback para nos avisar
//quando chegou algo do Master
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
  char macStr[18];
  //Copiamos o Mac Address origem para uma string
  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]);
  //Mostramos o Mac Address que foi a origem da mensagem
  Serial.print("Received from: "); 
  Serial.println(macStr);
  Serial.println("");

  //Para cada pino
  for(int i=0; i<gpioCount; i++){
    //Colocamos o valor recebido do Master na saída do respectivo pino
    digitalWrite(gpios[i], data[i]);

  Serial.println(data[i]);
    myservo.write(data[0]);                  // set the servo position according to the scaled value
                          // wait for the servo to get there
  }
}


void loop() {
  

}

Who is online

Users browsing this forum: No registered users and 54 guests