Using ESP_NOW to sendstrings

Stumpy_L
Posts: 10
Joined: Fri Feb 04, 2022 3:50 pm

Using ESP_NOW to sendstrings

Postby Stumpy_L » Sun Aug 04, 2024 8:02 pm

I am building a sip & puff control system so that a quadriplegic can control a RC boat or car. I had it working with Arduino Nanos and NRF24L Wi-Fi modules. Now I am converting it to use a ESP32 and ESP_NOW for communications, the NRF24L's give me troubles now and then plus it reduces the hardware I need.

I have the ESP_NOW working if I send static text, "TEXT", but I have two variables that give me direction, (Foward, Idle & Reverse), and steering, (Left & Right). I am also trying to put those variables in a structure text message. I've tried a few ways but none of them are working, or I wouldn't be asking.

So my two questions are, how do I get my variables into the structure text elements, and how do I send it via ESP_NOW/

Code is show below, these are both ESP32 DEV Modules and I'm programming them with the Arduino IDE rev 2.3.2

Thanks
John

Code: Select all

/* Started with sipPuffToyCar_Mod example
    added NRF24L01 communications
    with corrections from forum
    Rev 3 added steering state to receiver
    Rev 4 Added sip/puff delay on steering
    Rev 5 Replaced UNO and NRF24L with a ESP32 using ESP_NOW
*/

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

// REPLACE WITH YOUR RECEIVER MAC Address 
uint8_t broadcastAddress[] = {0x34, 0x86, 0x5D, 0x45, 0x9D, 0x7C}; 
esp_now_peer_info_t peerInfo; 

// Structure text to send data 
typedef struct struct_message { 
  char drive[32]; 
  char steering[32]; 
} struct_message; 
 
// Create a struct_message called myData 
struct_message myData; 

// callback when data is sent 
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { 
  Serial.print("\r\nLast Packet Send Status:\t"); 
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : 
"Delivery Fail"); 
}

cSF(drvText_SS, 24);
cSF(strText_SS, 24);

#define SENSOR_PIN 34

#define SIP_THRESHOLD 2400 //analog val, 450
#define PUFF_THRESHOLD 3000 //analog val, 550

#define POLL_INTERVAL 10 //ms

#define SHORT_ACTION_MIN 100 //ms
#define SHORT_ACTION_MAX 750 //ms
#define ACTION_SPACE_MIN 50 //ms
#define ACTION_SPACE_MAX 750 //ms

uint32_t sipStartTime;
uint8_t sipStarted = 0;
uint32_t lastSipTime;
uint32_t lastSipDuration;

uint32_t puffStartTime;
uint8_t puffStarted = 0;
uint32_t lastPuffTime;
uint32_t lastPuffDuration;

uint8_t ThrottleOutValue = 0;
uint8_t ThrottleTrimValue = 0;
uint8_t SteeringOutValue = 135;
uint8_t SteeringTrimValue = 0;

uint32_t SteeringDelay = 0;
uint32_t previousMillis = 0;
uint32_t StartSteeringDelay = 50;
uint8_t SteeringPause = 0;
uint32_t SteeringPauseDelay = 500;
uint32_t SteeringPauseStart = 0;

enum DRIVE_STATE {FORWARD, REVERSE, IDLE}; // Enumeration, FORWARD - 1, REVERSE = 2, IDLE = 3
char *DRIVE_STATE_STRS[] = {"forward", "reverse", "idle"}; // ? Defines words so that when Drive state = 1 Serial monitor will display Forward, etc
uint8_t driveState = IDLE;

void setDrive(uint8_t state) {
 
  if (driveState == state)
    return;

  if (state == FORWARD) {
   
     }
  else if (state == REVERSE) {
    
    }
  else {
   
  }
  driveState = state;
}

//
void toggleReverse() {
  if (driveState == REVERSE)
    return;

  else if (driveState == IDLE)
    setDrive(REVERSE);
  else
    setDrive(IDLE);
}


void toggleForward() {
  if (driveState == FORWARD)
    return;

  else if (driveState == IDLE)
    setDrive(FORWARD);
  else
    setDrive(IDLE);
}


enum STEERING_STATE {LEFT, RIGHT, CENTER};
char *STEERING_STATE_STRS[] = {"left", "right", "center"};
uint8_t steeringState = CENTER;


void setSteering(uint8_t state) {

  if (steeringState == state)
    return;

  if (state == LEFT) {
   
  }
  else if (state == RIGHT) {
  
  }
  else {
       SteeringPauseStart = millis();
    SteeringPause = 0;

    }
  steeringState = state;
} // end void setSteering(uint8_t state)


void setup() {
  Serial.begin(115299);
  
  // Set device as a Wi-Fi Station 
  WiFi.mode(WIFI_STA); 
 
  // Init ESP-NOW 
  if (esp_now_init() != ESP_OK) { 
    Serial.println("Error initializing ESP-NOW"); 
    return; 
  } 
 
  // Once ESPNow is successfully Init, we will register for Send CB to 
  // get the status of Trasnmitted packet 
  esp_now_register_send_cb(OnDataSent); 
   
  // Register peer 
  memcpy(peerInfo.peer_addr, broadcastAddress, 6); 
  peerInfo.channel = 0;   
  peerInfo.encrypt = false; 
   
  // Add peer         
  if (esp_now_add_peer(&peerInfo) != ESP_OK){ 
    Serial.println("Failed to add peer"); 
    return; 
  }
   
} // End ot Setup Loop


void loop() {
  
  int16_t val = analogRead(SENSOR_PIN); // Read Pressure Switch < 2000 = SIP, > 3000 = Puff
    
  if (!sipStarted && val < SIP_THRESHOLD) {
    SteeringPause = 1;
    sipStarted = 1;
    sipStartTime = millis(); //Store Sip Start Time
    }
  else if (sipStarted && val > SIP_THRESHOLD) {// SIP has Stopped
    sipStarted = 0;
    uint32_t duration = millis() - sipStartTime;
    
    if (duration > SHORT_ACTION_MIN) {
      uint32_t prevLastSipTime = lastSipTime;
      uint32_t prevLastSipDuration = lastSipDuration;

      lastSipTime = millis();
      lastSipDuration = duration;

      uint32_t space = sipStartTime - prevLastSipTime;

      //two shorts in a row
      if (prevLastSipDuration < SHORT_ACTION_MAX &&
          lastSipDuration < SHORT_ACTION_MAX &&
          space > ACTION_SPACE_MIN && space < ACTION_SPACE_MAX) {
        toggleReverse();
        }
    }
  }

  if (!puffStarted && val > PUFF_THRESHOLD) {
    SteeringPause = 1;
    puffStarted = 1;
    puffStartTime = millis();
  }
  else if (puffStarted && val < PUFF_THRESHOLD) {
    puffStarted = 0;
    uint32_t duration = millis() - puffStartTime;
    if (duration > SHORT_ACTION_MIN) {
      uint32_t prevLastPuffTime = lastPuffTime;
      uint32_t prevLastPuffDuration = lastPuffDuration;

      lastPuffTime = millis();
      lastPuffDuration = duration;

      uint32_t space = puffStartTime - prevLastPuffTime;

      //two shorts in a row
      if (prevLastPuffDuration < SHORT_ACTION_MAX &&
          lastPuffDuration < SHORT_ACTION_MAX &&
          space > ACTION_SPACE_MIN && space < ACTION_SPACE_MAX) {
        toggleForward();
      }
    }
  }

  //update steering
  if (sipStarted && (millis() > (sipStartTime + SteeringPauseDelay)))
    setSteering(LEFT);
  else if (puffStarted && (millis() > (puffStartTime + SteeringPauseDelay)))
    setSteering(RIGHT);
  else
    setSteering(CENTER);

  if (DRIVE_STATE_STRS[driveState] == "forward") {
   
  }
  else if (DRIVE_STATE_STRS[driveState] == "reverse") {
   
  }
  else {
   
  }
 
  unsigned long currentmillis = millis();
  int CenterStop ;

  if (currentmillis - previousMillis > StartSteeringDelay) {
    previousMillis = currentmillis;
    CenterStop = (135 + SteeringTrimValue);

    if ((STEERING_STATE_STRS[steeringState] == "right") && (SteeringOutValue < 230)) {

      SteeringOutValue = ((SteeringOutValue + 10) );
      
    }

    if ((STEERING_STATE_STRS[steeringState] == "left") && (SteeringOutValue > 40)) {
      SteeringOutValue = ((SteeringOutValue - 10)  );
     
    }

    if (STEERING_STATE_STRS[steeringState] == "center") {
      if (SteeringOutValue - CenterStop > 2) {
        SteeringOutValue = ((SteeringOutValue) - 5);
       }

      if (SteeringOutValue - CenterStop < -2) {
        SteeringOutValue = ((SteeringOutValue) + 5);
       }
    } // End of CENTER if
  } // End of Main Steering If loop

  drvText_SS = DRIVE_STATE_STRS[driveState];
 
  
      Serial.print("  Steering State =  ");
      Serial.print(STEERING_STATE_STRS[steeringState]);
      Serial.print("\t");
      Serial.print("  Drive State =  ");
      Serial.println(DRIVE_STATE_STRS[driveState]);
  strText_SS = STEERING_STATE_STRS[steeringState];
  
  delay(POLL_INTERVAL);

  // Set values to send 
   strcpy(myData.drive, "driveState");
   strcpy(myData.steering, "steeringState");
 //  myData.drive = (drvText_SS.c_str(), drvText_SS.length() )
 //  myData.steering = (strText_SS.c_str(), strText_SS.length() );
//  strcpy(myData.a, drvText_SS); 
//  strcpy(myData.b, strText_SS); 
  
 
  // Send message via ESP-NOW 
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, 
sizeof(myData)); 
    
  if (result == ESP_OK) { 
    Serial.println("Sent with success"); 
  } 
  else { 
    Serial.println("Error sending the data"); 
  } 
 // delay(2000); 
}


ESP_Sprite
Posts: 9764
Joined: Thu Nov 26, 2015 4:08 am

Re: Using ESP_NOW to sendstrings

Postby ESP_Sprite » Mon Aug 05, 2024 2:47 am

Can you define 'none of them are working'? How do you conclude that?

Stumpy_L
Posts: 10
Joined: Fri Feb 04, 2022 3:50 pm

Re: Using ESP_NOW to sendstrings

Postby Stumpy_L » Mon Aug 05, 2024 7:51 am

I didn't think it was necessary to go into details of what isn't working, but if you look at the end of the code under the comment "Set values to send" are a couple of the attempts.

I think part of the problem is the declaration of the variables in the structured message and how I am formatting that to send via ESP_Now.

Stumpy_L
Posts: 10
Joined: Fri Feb 04, 2022 3:50 pm

Re: Using ESP_NOW to sendstrings

Postby Stumpy_L » Mon Aug 05, 2024 11:35 am

I have a work around. I declared the elements in the structure text as integers then using a if/else statement I set the element to a number based on the drive status as shown below. I have a similar statement for the steering. I then can send the structured text to the receiver ESP32 then set the direction or steering based on the number. Seems to work fine.

Code: Select all

 // set drive integer to send
  if(drvText_SS == "forward"){
    myData.drive = 1;
  }
  else if(drvText_SS == "reverse"){
    myData.drive = 2;
  }
  else
    myData.drive = 0;
Just for my own education I would like to see if someone can tell me the pproper way to send a string variable via a strutured text and ESP_NOW.

Thanks
John

ESP_Sprite
Posts: 9764
Joined: Thu Nov 26, 2015 4:08 am

Re: Using ESP_NOW to sendstrings

Postby ESP_Sprite » Wed Aug 07, 2024 3:42 am

Stumpy_L wrote:
Mon Aug 05, 2024 7:51 am
I didn't think it was necessary to go into details of what isn't working, but if you look at the end of the code under the comment "Set values to send" are a couple of the attempts.
Yes, I saw that. What I cannot see is a. the receiving code, and b. what the result of the receiving code receiving a transmission is. You seem to be focusing on your transmit code, but the thing is that you may be sending it 100% correctly but due to an error in the receiver you think it's not working.

Who is online

Users browsing this forum: No registered users and 77 guests