Error sending data between two Arduino Yun over WiFi (with NewPing Library)

My project is using 2 ultrasonic sensor (HC-SR04) to measure speed of moving things. The output of sensors is processed by Arduino Yun 1, then it will be transmitted over wifi network (port 5555) to Arduino Yun 2 for another process.

The problem is, when I don’t activated the transmitting part, and just display the sensors output to Serial monitor, it works fine. But, when I want to transmit it, the data sometime is 0.00 and not changing, or a float data but not changing afterwards… I’m using NewPing Library for sensor reading. I don’t know if I use the wrong algorithm or it is the library fault.

Please help me correct this mess.

Code for Arduino Yun 1

#include <YunClient.h>
#include <NewPing.h>

#define SONAR_NUM      2 // Number of sensors.
#define MAX_DISTANCE 10 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

IPAddress server(192,168,43,57);  //Because Yun2 has this IP adress
YunClient client;
unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.
unsigned long start=0, finish=0;
float velocity=0;
NewPing sonar[SONAR_NUM]={   // Sensor object array.
  NewPing(2, 3, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(4, 5, MAX_DISTANCE)
};

void setup() {
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
  Bridge.begin();
  digitalWrite(13,HIGH);
  pingTimer[0]=millis()+75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  pingTimer[1]=pingTimer[0]+PING_INTERVAL;
}

void loop() {
  if (millis() >= pingTimer[0]) {         // Is it this sensor's time to ping?
      pingTimer[0] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      sonar[1].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = 0;                          // Sensor being accessed.
      sonar[0].ping_timer(echoCheck0); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
  }
  if (millis() >= pingTimer[1]) {         // Is it this sensor's time to ping?
      pingTimer[1] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      sonar[0].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = 1;                          // Sensor being accessed.
      sonar[1].ping_timer(echoCheck1); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
  }
  if(client.connect(server,5555)) client.println(velocity);//the transmitting part
  client.stop();
}

void echoCheck0() { 
  if (sonar[currentSensor].check_timer()) start = millis();
}

void echoCheck1() { 
  if ((sonar[currentSensor].check_timer())&&(start != 0)) {
    finish = millis() - start;
    velocity = 15.3 / (finish/1000.00); //  15.3 / finish / 1000 (cm/s)
    start = 0;
  }
}

Code for Arduino Yun 2

#include <YunServer.h> 
#include <YunClient.h>
#include <Console.h>
#include <Servo.h>

//Servo servo;
YunServer server;
float velocity;

void setup() 
{
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
  Bridge.begin();
  server.begin();
  //servo.attach(9);
  Serial.begin(9600);
  digitalWrite(13,HIGH);
}

void loop() 
{
  YunClient client = server.accept();
  if(client){
    while(client.available()<1);
    velocity=client.parseFloat();
    Serial.println(velocity,DEC);
    client.stop();
  }
}

Can you code and show a version of the first sketch that both prints on the serial monitor and send the value to the other yun?

I have a theory: (based on reading docs and looking at samples, I’ve not tried doing this yet.)

In the code for Yun2, you have a null loop that waits for the first character to be available from the client connection (while available <1)

Once the first character arrives, you try to parse a float using whatever data is available at that instant, which is likely to be just that one character. Since you are using println to send the data, you have a built in terminator (the newline char.) I think you need a loop to keep reading characters and put them in a buffer, until you see the newline character. Then you can parse the buffer to extract your float.

My understanding is that when a REST API call comes in, all of the data is already available, so calling parseint or paresefloat directly works. But with a client connection, that isn’t the case and you need to wait until all of the necessary characters are received?

The code for just read the sensor and calculate and printing the value of velocity to serial monitor in Yun 1:

#include <YunClient.h>
#include <NewPing.h>

#define SONAR_NUM      2 // Number of sensors.
#define MAX_DISTANCE 10 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

IPAddress server(192,168,43,57);  //Because Yun2 has this IP adress
YunClient client;
unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.
unsigned long start=0, finish=0;
float velocity=0;
NewPing sonar[SONAR_NUM]={   // Sensor object array.
  NewPing(2, 3, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(4, 5, MAX_DISTANCE)
};

void setup() {
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
  Bridge.begin();
  Serial.begin();
  digitalWrite(13,HIGH);
  pingTimer[0]=millis()+75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  pingTimer[1]=pingTimer[0]+PING_INTERVAL;
}

void loop() {
  if (millis() >= pingTimer[0]) {         // Is it this sensor's time to ping?
      pingTimer[0] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      sonar[1].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = 0;                          // Sensor being accessed.
      sonar[0].ping_timer(echoCheck0); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
  }
  if (millis() >= pingTimer[1]) {         // Is it this sensor's time to ping?
      pingTimer[1] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      sonar[0].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = 1;                          // Sensor being accessed.
      sonar[1].ping_timer(echoCheck1); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
  }
}

void echoCheck0() { 
  if (sonar[currentSensor].check_timer()) start = millis();
}

void echoCheck1() { 
  if ((sonar[currentSensor].check_timer())&&(start != 0)) {
    finish = millis() - start;
    velocity = 15.3 / (finish/1000.00); //  15.3 / finish / 1000 (cm/s)
    Serial.println(velocity);
    start = 0;
  }
}

The code for just connecting to Yun 2 and send a value from Yun 1:

#include <YunClient.h>
IPAddress server(192,168,43,57);  

void setup() {
  Bridge.begin();
}

void loop() {
  YunClient client;
  if(client.connect(server,5555)){
      client.write(47); //a random number I put only for test the connection
  }
  client.stop();
}

Both code if uploaded separately works fine. But when I combine them, it’s not work as I expected. Do you have any idea why?

ShapeShifter:
I have a theory: (based on reading docs and looking at samples, I’ve not tried doing this yet.)

In the code for Yun2, you have a null loop that waits for the first character to be available from the client connection (while available <1)

Once the first character arrives, you try to parse a float using whatever data is available at that instant, which is likely to be just that one character. Since you are using println to send the data, you have a built in terminator (the newline char.) I think you need a loop to keep reading characters and put them in a buffer, until you see the newline character. Then you can parse the buffer to extract your float.

My understanding is that when a REST API call comes in, all of the data is already available, so calling parseint or paresefloat directly works. But with a client connection, that isn’t the case and you need to wait until all of the necessary characters are received?

Do you know how to implement REST API between 2 Arduino Yun? I’m still trying to find some alternative solution for this project.