ESP Now values not being received properly on receiver side.

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

ESP Now values not being received properly on receiver side.

Postby knightridar » Fri Nov 08, 2019 2:33 am

I'm reading 4 analog values after smoothing the results from a multidimensional array.

Based on the results of the analog values I output certain data variable values.
These data variable values should get transferred to the receiver/slave ESP32 but they are not.
I'm using the ESP-Now protocol to transfer the values.

I'm getting conflicting results from the serial monitor output of the ESP32 slave.
It' not getting the correct data variable values on the slave end.
I've confirmed it by placing my hands on the photodiode sensors and the ESP32 master sender values are correct in the serial monitor.

Any idea what could be wrong?
I'm suspecting on the receiver/slave side the data variable is not being received properly.
Esp32EspNowDataSent_R1.zip
(2.5 KiB) Downloaded 435 times
Esp32EspNowDataRcvd_R1.zip
(2.05 KiB) Downloaded 494 times
Esp32 Master Serial out:

Code: Select all

Success
AzimuthCW: 0
AzimuthCCW: 0
ElevationCW: 0
ElevationCCW: 0
2
5
Success
AzimuthCW: 0
AzimuthCCW: 0
ElevationCW: 0
ElevationCCW: 0
2
5
Success
Esp32 Slave Serial out:

Code: Select all

3
ELEVATION MOTOR MOVES CLOCKWISE
 
6
ELEVATION MOTOR STOPS
 
1
AZIMUTH MOTOR MOVES COUNTERCLOCKWISE
 
3
ELEVATION MOTOR MOVES CLOCKWISE
 
6
ELEVATION MOTOR STOPS
 
1
AZIMUTH MOTOR MOVES COUNTERCLOCKWISE
I'm not worried about the 6 value right now since I still have to hook up that sensor on the Master side.

Master code:

Code: Select all

/*
    Free and open source, CC BY-SA 4.0

    https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
    https://docs.espressif.com/projects/esp-idf/en/stable/api-reference/wifi/esp_now.html

    http://www.arduino.cc/en/Tutorial/Smoothing
*/

//ESP-Now WiFi power saving protocol
#include <esp_now.h>
#include <WiFi.h>

// Channel used for connection
#define CHANNEL 1

// ESP32 adc conversion
#include <driver/adc.h>

// Structure with information about the next peer
esp_now_peer_info_t peer;

// Master Mac Address: D8:A0:1D:69:F8:30
// Mac Address of the peer to which we will send the data, D8:A0:1D:6A:00:58
uint8_t peerMacAddress[] = {0xD8, 0xA0, 0x1D, 0x6A, 0x00, 0x58};

int8_t ElevationAngle;
uint8_t ElevationAngleLimit = 70;

uint8_t Tolerance = 100;

uint8_t data;

// 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
// data to determine the size of the readings array.
const uint8_t numReadings = 64;
const uint8_t numSensors = 4;

uint32_t readings[numSensors][numReadings];   // multi-dimensional readings from analog input
uint32_t readIndex = 0;              // the index of the current reading
uint32_t total[numSensors] = {0};    // the running total
uint32_t average = 0;                // the average

// interval to stabilize analog input smoothing readings
// ADC1 Channel read time ~9.5µs per sample --> 64 readings x 9.5 = 608 µs = .608 ms
uint8_t numReadingsInterval = 2;
uint32_t numReadingsStart = 0;

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

  // Voltage divider analog in pins
  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

  adc1_config_width(ADC_WIDTH_12Bit);
  adc1_config_channel_atten(ADC1_CHANNEL_1, ADC_ATTEN_DB_11); //Pin37

  adc1_config_width(ADC_WIDTH_12Bit);
  adc1_config_channel_atten(ADC1_CHANNEL_2, ADC_ATTEN_DB_11); //Pin38

  // initialize all the readings to 0
  // multidimensional array takes into account multiple sensors and multiple readings for each sensor
  for (uint8_t thisReading = 0; thisReading < numReadings; thisReading++)
  {
    for ( uint8_t j = 0; j < numSensors; j++)  readings[j][thisReading] = 0;
  }

  // Call the function that initializes the station mode
  modeStation();

  // Call function that initializes ESPNow
  InitESPNow();

  // Add the peer
  addPeer(peerMacAddress);

  // Registers the callback that will inform us about the status of the submission.
  // The function that will be executed is onDataSent and is stated below
  esp_now_register_send_cb(OnDataSent);
}

//loop function being used to smooth analog input values
// void OnDataSent function sends values over and over again
void loop() {
  if ( millis() - numReadingsStart >= numReadingsInterval * numReadings )
  {
    numReadingsStart = millis();

    // Read the sensor
    uint16_t AzimuthCW = adc1_get_raw(ADC1_CHANNEL_6); //Pin34
    uint16_t AzimuthCCW = adc1_get_raw(ADC1_CHANNEL_7); //Pin35

    uint16_t ElevationCW = adc1_get_raw(ADC1_CHANNEL_1); //Pin37
    uint16_t ElevationCCW = adc1_get_raw(ADC1_CHANNEL_2); //Pin38

    uint16_t  inputPin[ numSensors ] = {AzimuthCW, AzimuthCCW, ElevationCW, ElevationCCW};

    uint8_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;
    }

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

    uint16_t ACW = total[0] / numReadings; // AzimuthCW
    uint16_t ACCW = total[1] / numReadings; // AzimuthCCW
    uint16_t ECW = total[2] / numReadings; // ElevationCW
    uint16_t ECCW = total[3] / numReadings; // ElevationCCW

    Serial.print("AzimuthCW: ");
    Serial.println(ACW);
    Serial.print("AzimuthCCW: ");
    Serial.println(ACCW);
    Serial.print("ElevationCW: ");
    Serial.println(ECW);
    Serial.print("ElevationCCW: ");
    Serial.println(ECCW);
    
    if (ACW < ACCW)
    {
      data = 0;
      Serial.println(data);
    }

    else if (ACW > ACCW)
    {
      data = 1;
      Serial.println(data);
    }

    else if (abs(ACW - ACCW)  < Tolerance)
    {
      data = 2;
      Serial.println(data);
    }

    if (ECW < ECCW)
    {
      data = 3;
      Serial.println(data);
    }

    else if (ECW > ECCW)
    {
      data = 4;
      Serial.println(data);
    }

    else if (abs(ECW - ECCW) < Tolerance)
    {
      data = 5;
      Serial.println(data);
    }

    if (ElevationAngle > ElevationAngleLimit)
    {
      data = 6;
    }

    readAndSend();
  }
}

// Function responsible for pin reading and sending of data to the peer
void readAndSend() {
  // Send the data to the peer
  send(&data, peerMacAddress);
}

// Function that serves as a callback to warn us about the sending situation we made
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
}

// Function to initialize the station mode
void modeStation() {
  // We put the ESP in station mode
  WiFi.mode(WIFI_STA);
  // We show on Serial Monitor the Mac Address
  // of this ESP when in station mode
  Serial.print("Mac Address in Station: ");
  Serial.println(WiFi.macAddress());
}

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

// Function that adds a new peer through your MAC address
void addPeer(uint8_t *peerMacAddress) {
  // We inform the channel
  peer.channel = CHANNEL;
  // 0 not to use encryption or 1 to use
  peer.encrypt = 0;
  // Copy array address to structure
  memcpy(peer.peer_addr, peerMacAddress, 6);
  // Add slave
  esp_now_add_peer(&peer);
}

// Function that will send the data to the peer that has the specified mac address
void send(const uint8_t *data, uint8_t *peerMacAddress) {
  esp_err_t result = esp_now_send(peerMacAddress, data, sizeof(data));
}
Slave code:

Code: Select all

/*  
    Free and open source, CC BY-SA 4.0
    
    https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
    https://docs.espressif.com/projects/esp-idf/en/stable/api-reference/wifi/esp_now.html
   
    http://www.arduino.cc/en/Tutorial/Smoothing
*/

//ESP-Now WiFi power saving protocol
#include <esp_now.h>
#include <WiFi.h>

// Channel used for connection
#define CHANNEL 1

uint8_t data;

uint16_t period = 2000;
unsigned long time_now = 0;

// Azimuth and elevation pwm (pulse width modulation) pins on each h-bridge must be connected to four pwm pins on microprocessor.
// For ESP32 the GPIO pwm pins are: 0,1,2,3,4,6,7,8,9,10,11,12,14,16,17,18,19,21,22,23,25,26,27,32,33,34,35,36,39

// motor azimuth adjustment
uint8_t AzimuthClockwiseEnable = 26;
uint8_t AzimuthCounterClockwiseEnable = 27;

uint8_t AzimuthClockwisePWM = 32;
uint8_t AzimuthCounterClockwisePWM = 33;

// motor elevation adjustment
uint8_t ElevationClockwiseEnable = 34;
uint8_t ElevationCounterClockwiseEnable = 35;

uint8_t ElevationClockwisePWM = 36;
uint8_t ElevationCounterClockwisePWM = 37;

// Setting PWM properties
uint16_t freq = 30000;
uint8_t resolution = 8;
uint8_t DutyCycleAzimuthCW = 200;
uint8_t DutyCycleAzimuthCCW = 200;
uint8_t DutyCycleElevationCW = 200;
uint8_t DutyCycleElevationCCW = 200;

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

  // Call the function that initializes the station mode
  modeStation();

  // Call function that initializes ESPNow
  InitESPNow();

  // Registers the callback that will inform us that we receive data. The function to be executed is onDataRecv and is declared below
  esp_now_register_recv_cb(onDataRecv);

  // Registers the callback that will inform us
  // about the status of the submission.
  // The function to be executed
  // is onDataSent and is declared below
  esp_now_register_send_cb(onDataSent);

  //set all motor control pins to outputs
  pinMode(AzimuthClockwiseEnable, OUTPUT);
  pinMode(AzimuthCounterClockwiseEnable, OUTPUT);

  pinMode(AzimuthClockwisePWM, OUTPUT);
  pinMode(AzimuthCounterClockwisePWM, OUTPUT);

  pinMode(ElevationClockwiseEnable, OUTPUT);
  pinMode(ElevationCounterClockwiseEnable, OUTPUT);

  pinMode(ElevationClockwisePWM, OUTPUT);
  pinMode(ElevationCounterClockwisePWM, OUTPUT);

  // configure LED PWM functionalitites
  ledcSetup(AzimuthClockwisePWM, freq, resolution);
  ledcSetup(AzimuthCounterClockwisePWM, freq, resolution);

  ledcSetup(ElevationClockwisePWM, freq, resolution);
  ledcSetup(ElevationCounterClockwisePWM, freq, resolution);

  // attach the channel to the GPIO to be controlled
  ledcAttachPin(AzimuthClockwiseEnable, AzimuthClockwisePWM);
  ledcAttachPin(AzimuthCounterClockwiseEnable, AzimuthCounterClockwisePWM);

  ledcAttachPin(ElevationClockwiseEnable, ElevationClockwisePWM);
  ledcAttachPin(ElevationCounterClockwiseEnable, ElevationCounterClockwisePWM);
}

// We send the data as soon as we get from the other esp by the callback
void loop()
{
  if (millis() > time_now + period) 
  {
    time_now = millis();
  }

  if (data = 0) // if average light sensor values on left side are greater than right side, azimuth motor rotates clockwise
  {
    digitalWrite(AzimuthClockwiseEnable, HIGH); ledcWrite(AzimuthClockwisePWM, DutyCycleAzimuthCW); // set speed out of possible range 0~255
    digitalWrite(AzimuthCounterClockwiseEnable, HIGH); digitalWrite (AzimuthCounterClockwisePWM, LOW);
    Serial.println(data);
    Serial.println("AZIMUTH MOTOR MOVES CLOCKWISE");
    Serial.println("   ");
  }
  else if (data = 1)// if average light sensor values on right side are greater than on left side, azimuth motor rotates counterclockwise
  {
    digitalWrite(AzimuthCounterClockwiseEnable, HIGH); ledcWrite(AzimuthCounterClockwisePWM, DutyCycleAzimuthCCW);
    digitalWrite(AzimuthClockwiseEnable, HIGH); digitalWrite(AzimuthClockwisePWM, LOW);
    Serial.println(data);
    Serial.println("AZIMUTH MOTOR MOVES COUNTERCLOCKWISE");
    Serial.println(" ");
  }
  else if (data = 2) // if difference is smaller than tolerance, stop azimuth motor
  {
    digitalWrite(AzimuthClockwiseEnable, LOW); digitalWrite(AzimuthCounterClockwiseEnable, LOW);
    Serial.println("AZIMUTH MOTOR STOPS");
    Serial.println(" ");
  }

  if (data = 3) // if average light sensor value on top side is greater than on bottom side then elevation motor rotates clockwise
  {
    digitalWrite(ElevationClockwiseEnable, HIGH); ledcWrite(ElevationClockwisePWM, DutyCycleElevationCW);
    digitalWrite(ElevationCounterClockwiseEnable, HIGH); digitalWrite(ElevationCounterClockwisePWM, LOW);
    Serial.println(data);
    Serial.println("ELEVATION MOTOR MOVES CLOCKWISE");
    Serial.println(" ");
  }
  else if (data = 4) // if average light sensor value on bottom side is greater than on top side then elevation motor rotates counterclockwise
  {
    digitalWrite(ElevationCounterClockwiseEnable, HIGH); ledcWrite(ElevationCounterClockwisePWM, DutyCycleElevationCCW);
    digitalWrite(ElevationClockwiseEnable, HIGH); digitalWrite(ElevationClockwisePWM, LOW);
    Serial.println(data);
    Serial.println("ELEVATION MOTOR MOVES COUNTERCLOCKWISE");
    Serial.println(" ");
  }
  else if (data = 5) // if difference is smaller than tolerance, stop elevation motor
  {
    digitalWrite(ElevationClockwiseEnable, LOW); digitalWrite(ElevationCounterClockwiseEnable, LOW);
    Serial.println(data);
    Serial.println("ELEVATION MOTOR STOPS");
    Serial.println(" ");
  }
  if (data = 6)
  {
    digitalWrite(ElevationClockwiseEnable, LOW); digitalWrite(ElevationCounterClockwiseEnable, LOW);
    Serial.println(data);
    Serial.println("ELEVATION MOTOR STOPS");
    Serial.println(" ");
  }
}


// Function that serves as a callback to warn us we received data
void onDataRecv(const uint8_t *mac_addr, const uint8_t *data, int len) {
  // Place the received data at the output of the pin
  Serial.println(*data);
}

// Function that serves as a callback to warn us about the sending situation we made
void onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
}

// Function to initialize the station mode
void modeStation() {
  // We put the ESP in station mode
  WiFi.mode(WIFI_STA);
  // We show on Serial Monitor the Mac Address
  // of this ESP when in station mode
  Serial.print("Mac Address in Station: ");
  Serial.println(WiFi.macAddress());
}

// ESPNow startup function
void InitESPNow() {
  // If the initialization was successful
  if (esp_now_init() == ESP_OK) {
    Serial.println("ESPNow Init Success");
  }
  // If initialization failed
  else {
    Serial.println("ESPNow Init Failed");
    ESP.restart();
  }
}
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

idahowalker
Posts: 166
Joined: Wed Aug 01, 2018 12:06 pm

Re: ESP Now values not being received properly on receiver side.

Postby idahowalker » Fri Nov 08, 2019 2:49 am

Just courious if you expect these values to go negative

Code: Select all

uint16_t ACW = total[0] / numReadings; // AzimuthCW
    uint16_t ACCW = total[1] / numReadings; // AzimuthCCW
    uint16_t ECW = total[2] / numReadings; // ElevationCW
    uint16_t ECCW = total[3] / numReadings; // ElevationCCW
?

A uint16_t cannot store a negative number.

idahowalker
Posts: 166
Joined: Wed Aug 01, 2018 12:06 pm

Re: ESP Now values not being received properly on receiver side.

Postby idahowalker » Fri Nov 08, 2019 2:56 am

This is not true

Code: Select all

// For ESP32 the GPIO pwm pins are: 0,1,2,3,4,6,7,8,9,10,11,12,14,16,17,18,19,21,22,23,25,26,27,32,33,34,35,36,39
All the GPIO pins above 32 are input only

Code: Select all

// For ESP32 the GPIO pwm pins are: 0,1,2,3,4,6,7,8,9,10,11,12,14,16,17,18,19,21,22,23,25,26,27,32
is correct.

Anyway, not used esp_now(). I like to think of the data sent as a sentence. As such I put a sentence begin and end marker with the sentence meat.

If I want to send 1,2,3,4,5, I send <1,2,3,4,5>. If I get 3,4,5> that's not a valid data receipt, so I ignore it.

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

Re: ESP Now values not being received properly on receiver side.

Postby knightridar » Fri Nov 08, 2019 7:25 pm

Thanks for the PWM update. I got it from various websites and their images of pinouts.

The values will not go negative.

Since they are from ADC they will range from 0-4095.
The total/numReadings will yield a result in that range.

I used the <1,2,3,4,5> method via Arduino Pro Mini and HC-12 wireless module via software serial.
It worked but needed to error proof it.

ESP-Now supposedly saves more power for wireless transmission.
I'm using it since I'm powering the ESP32 with a small 3.5V solar panel and I want to use it without a battery.
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

Who is online

Users browsing this forum: PepeTheGreat and 56 guests