Go Down

Topic: speed measurement with 2 arduino boards wireless connected (Read 454 times) previous topic - next topic

pbak1967

Hi,

I have 2 UNO boards, eacht board has a sensor and a HC12 module. I want the first board to detect an object with the sensor and send the nummer of millis that are passed since startup to the second board. The second board also detects the object passing by and calculates the millis from the fist board with its own millis.

Ofcourse there must be an initialising phase where the delta in millis since startup between the to boards are calculated. So during this phase board 1 sends a couple of times its millis and the second boards captures this and calculates the delta millis. So the speed calculation must consider this delta.


The software on the boards are up and running and I am trying to set up the init phase, but I see that the delta keeps changing. For every 1000ms the calculated delta increases with 2 ms.

Is this a wrong approach?

blh64


Robin2

The problem is the length of time it takes for a wireless message to be sent and received. There is no guarantee that it will take any specific amount of time - for example a message might be garbled and need to be re-sent.

If the sending Arduino records the value of millis() when something happens and later sends that number together with its latest value of millis() AND IF the message can be assumed to have arrived as soon as possible the receiving Arduino could work out how long ago (relative to its own values for millis() ) the event was detected.

For example suppose the event was timed by the first Arduino at 56007 millis() and the message was sent at 69334 millis() and was received by the second Arduino at 8347 millis()  (according to its clock) and the second event happened at 9227 millis() it would be clear that according to the clock of the receiving Arduino the first event happened at 8347 - (69334 - 56007) = -4980 millis() so the elapsed time would be 9227 - (-4980) = 14207 millisecs.

However if it takes an appreciable amount of time for the message to arrive then there will be an error in the calculation. And "appreciable amount of time" depends very much on how accurate the time measurement needs to be.

It would be instructive to set up a test in which the message is sent both by wire and by wireless. However the wireless evidence will only be valid for that occasion at that location.


I have not used a HC12 (only nRF24L01+ modules) so I don't know if it has an automatic acknowledgement system that would allow the sender to know is a message was received. If it has then that could be used to help with the reliability by allowing a failed message to be resent with an updated value of the sender's current value of millis()

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Geek Emeritus

Quote
I have not used a HC12 (only nRF24L01+ modules) so I don't know if it has an automatic acknowledgement system that would allow the sender to know is a message was received.
just plain old fashioned half duplexSerial data, no ack, no checksum.
All PMs will be deleted unopened due to arrogant argumentative pot stirring Malfoys.
 If you have not read "How to use this forum - please read", in particular: "7. If you are posting code or error messages, use "code" tags":  expect rude responses

edmcguirk

I would have transmitter1 send messages on the second and transmitter2 send messages on the half second. Transmitter2 would save the millisecond it received the message from transmitter1 and send that data back along with any measurements.

Transmitter1 would then be able to calculate the round trip delay time and you could assume that the one way delay is half that. If the transmitters are motionless and calculation of the delay is consistent over many communication loops, you would have a reasonable guess of the clock offset of the timer in transmitter2.

Your accuracy would be as small as the variation in the loop delay times.

Robin2

you would have a reasonable guess of the clock offset of the timer in transmitter2.
I reckon if the sender includes its own millis() value at the time of sending there is no need to figure out the clock offset.

However it would be important to do tests to figure out if the length of time between sending and receiving is short enough not to matter.

If, as @Geek Emeritus has said, the data is sent in Serial format the transmission rate is likely to be slow and it would perhaps be essential to adjust the time calculations to allow for the baud-rate and the number bytes of data.

And it seems to me that a pair of nRF24L01+ modules might be more suitable if the two Arduinos are within their range.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

JCA79B

When the first radio is triggered, just send an empty byte. Have the second radio polling the data received bit in a tight loop, when the received bit changes state, start the timer, when the second radio is triggered by the passing target, stop the timer and and do the stop - start math.
 

edmcguirk

I reckon if the sender includes its own millis() value at the time of sending there is no need to figure out the clock offset.
If you know the other transmitter sends data only on the half second, you already know the other transmitter's timestamp.

Robin2

If you know the other transmitter sends data only on the half second, you already know the other transmitter's timestamp.
Only if a message is never dropped.

Or what happens if the sender is reset without going through a new SYNC routine?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

edmcguirk

Only if a message is never dropped.

Or what happens if the sender is reset without going through a new SYNC routine?

...R
Well,if the message is dropped, the data is lost anyway. My suggestion implies that all communication starts with a message from transmitter1 and ends with a reply from transmitter2 that includes the sent timestamp from transmitter1 and transmitter2 synchronizes its transmission window to its reception from transmitter1.

If there is a any reset, the whole sync process needs to start over.

I like sending on clock pulses over sending arbitrarily with a timestamp only because it also helps avoid collisions if all transmitters are time coordinated. Provided you have idle time and clean environment.

You could just as easily always send the external timestamp of the last received message with the internal timestamp of the current sent message during the same anti-collision windows for the cost of a little more data in the package.

You could save even more data in the package if you send your reply exactly 500 milliseconds after receiving a message with your timestamp referenced to when you received the first message.

pbak1967

thanks for your reactions. I made the whole setup a lot simpeler for testing purposes.

To skip the wireless part I connected the TX/RX from the second Arduino to the first one.

With the first arduino I send every second the millis counter.
The second arduino receives this counter, compares this with its own counter and shows the delta.

Still the delta value increases with about 2 ms every second. What am I doing wrong here?


First arduino:


#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX
unsigned long counter = 0;
 

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
  }
  mySerial.begin(9600);
  Serial.println("Port init ok");

}

void loop()
{

    counter = millis();
    mySerial.print(counter);  //send counter to the serial port
    Serial.println(counter);  // send countr to the serial monitor
    delay(1000);
}


Second arduino:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX
unsigned long counter = 0;
unsigned long counter2 = 0;
 

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {  }

  mySerial.begin(9600);
  Serial.println("Port init ok");
}

void loop() { // run over and over
     
  if (mySerial.available()) {
    counter = mySerial.parseInt();
    if (counter == 0) return;
    counter2 = millis();
    Serial.print("Counter  : ");Serial.println(counter);
    Serial.print("Counter 2: ");Serial.println(counter2);
    Serial.print("Delta    : ");Serial.println(counter2 - counter);     
  }
}















Robin2

You can't use Serial.parseInt() for this sort of thing because it is a blocking function and could itself be responsible for the problem.

Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

The technique in the 3rd example will be the most reliable. It is what I use for Arduino to Arduino and Arduino to PC communication.

You can send data in a compatible format with code like this (or the equivalent in any other programming language)
Code: [Select]
Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker



Also, use the highest baud rate that you could use with the HC12.


HOWEVER ...
I don't think this matters
Quote
Still the delta value increases with about 2 ms every second.
All that is important is whether the elapsed time (between something being detected by the first Arduino and the other thing being detected by the second Arduino) when calculated by the second Arduino is the same as when you measure it with a stop watch, or with a single Arduino detecting both events.

...R

Two or three hours spent thinking and reading documentation solves most programming problems.

pbak1967

does the parseint function really blocks the millis of micros from counting on?? Thas sounds crazy, but I will ofcourse try the code from the example and will post the results here.

I do beleive that getting a steady delta value is important. All I want is to know the delta in millis passed from both boards. How else could I have a stopwatch function with two arduino boards communicating via the air?
the latency between transmiiting and sending can not affect the stopwatch function. So with a good delta I can caluculate the passing time, even when there was a delay in the trasmission.

I will start changing the code and post the result.



 

pbak1967

I changed the code, but there is no difference. Here you can see that the delta increases.
Communication through connecting TX/RX directly. The code is at hte bottom of this post.


Counter  : 10062   (millis sent from arduino one to arduino 2)
Counter 2: 13787  (millis from arduino 2)
Delta    : 3725

Counter  : 11071
Counter 2: 14796
Delta    : 3725

Counter  : 12079
Counter 2: 15806
Delta    : 3727

Counter  : 13086
Counter 2: 16817
Delta    : 3731

Counter  : 14094
Counter 2: 17826
Delta    : 3732

Counter  : 15101
Counter 2: 18836
Delta    : 3735

Counter  : 16110
Counter 2: 19847
Delta    : 3737

Counter  : 17118
Counter 2: 20856
Delta    : 3738

Counter  : 18125
Counter 2: 21866
Delta    : 3741

Counter  : 19133
Counter 2: 22876
Delta    : 3743

Counter  : 20142
Counter 2: 23886
Delta    : 3744

Counter  : 21149
Counter 2: 24896
Delta    : 3747

Counter  : 22157
Counter 2: 25906
Delta    : 3749


Code Arduino one:



#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX
unsigned long counter = 0;
 

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
  }
  mySerial.begin(9600);
  Serial.println("Port init ok");

}

void loop()
{
    counter = millis();
    mySerial.print('<');
    mySerial.print(counter);  //send counter to the serial port
    mySerial.print('>');
   
    Serial.print('<');
    Serial.print(counter);  // send countr to the serial monitor
    Serial.println('>');   
    delay(1000);
}


Code Arduino two


#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX
unsigned long counter = 0;
unsigned long counter2 = 0;
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;


void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {  }

  mySerial.begin(9600);
  Serial.println("Port init ok");
}

void loop()
{ // run over and over
    recvWithStartEndMarkers();
    showNewData();
}

     
void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
    while (mySerial.available() > 0 && newData == false) {
        rc = mySerial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        //Serial.print("This just in ... ");
        counter = atoi(receivedChars);
        counter2 = millis();
        Serial.print("Counter  : ");Serial.println(counter);
        Serial.print("Counter 2: ");Serial.println(counter2);
        Serial.print("Delta    : ");Serial.println(counter2 - counter);     
        Serial.println("");     
       
        newData = false;
    }
}


Paul_KD7HB

Did you swap the two Arduinos and check the delta?

Paul

Go Up