TFMini LiDAR Processing Readings Separately

I have a basic knowledge of Arduino code. I am using an Arduino Uno Board connected to my laptop through USB. I have the green (Transmit) cable of a TFMini infra red distance sensor connected to the Rx in port on my Arduino. The code below is based on the link GitHub - TFmini/TFmini-Arduino: TFmini's Examples on Arduino. and works fine: I get a LIVE real-time distance and strength reading on the serial monitor in the Arduino IDE and there is a small but acceptable ‘lag’ or hysteresis when I move my hand up and down above the sensor.

//source:  https://github.com/TFmini/TFmini-Arduino


int distance = 0;
int strength = 0;
boolean receiveComplete = false;

void getTFminiData(int* distance, int* strength, boolean* complete) {
  static char i = 0;
  char j = 0;
  int checksum = 0;
  static int rx[9];
  if (Serial.available()) {
    rx[i] = Serial.read();
    if (rx[0] != 0x59) {
      i = 0;
    } else if (i == 1 && rx[1] != 0x59) {
      i = 0;
    } else if (i == 8) {
      for (j = 0; j < 8; j++) {
        checksum += rx[j];
      }
      if (rx[8] == (checksum % 256)) {
        *distance = rx[2] + rx[3] * 256;
        *strength = rx[4] + rx[5] * 256;
        *complete = true;
      }
      i = 0;
    } else {
      i++;
    }
  }
}

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

void loop() {
  if (receiveComplete) {
    receiveComplete = false;
    Serial.print(distance);
    Serial.print("cm\t");
    Serial.print("strength: ");
    Serial.println(strength);
    delay(100);  //seems to tolerate some delay in sketch, lag is ok....
  }
}

void serialEvent() {
  getTFminiData(&distance, &strength, &receiveComplete);
}

My goal is to modify the above code to take one distance reading from the one before it. Eventually I want to calculated the speed of approaching objects. For now I am using the code below to Serial.println a distance (distance1) and a subsequent distance (distance2).

//#include <SoftwareSerial.h>  //header file of software serial port


//SoftwareSerial Serial1 (2,3); //define software serial port name as Serial1 and define pin2 as RX and pin3 as TX


int distance1 = 0;
int strength1 = 0;
boolean receiveComplete1 = false;

int distance2 = 0;
int strength2 = 0;
boolean receiveComplete2 = false;

void getTFminiData1(int* distance1, int* strength1, boolean* complete1) {
  Serial.println("A");
  static char i = 0;
  char j = 0;
  int checksum = 0;
  static int rx[9];
  if (Serial.available()) {
    rx[i] = Serial.read();
    if (rx[0] != 0x59) {
      i = 0;
    } else if (i == 1 && rx[1] != 0x59) {
      i = 0;
    } else if (i == 8) {
      for (j = 0; j < 8; j++) {
        checksum += rx[j];
      }
      if (rx[8] == (checksum % 256)) {
        *distance1 = rx[2] + rx[3] * 256;
        *strength1 = rx[4] + rx[5] * 256;

        *complete1 = true;
      }
      i = 0;

    } else {
      i++;

    }
  }
}

void getTFminiData2(int* distance2, int* strength2, boolean* complete2) {
  Serial.println("B");
  static char i = 0;
  char j = 0;
  int checksum = 0;
  static int rx[9];
  if (Serial.available()) {
    rx[i] = Serial.read();
    if (rx[0] != 0x59) {
      i = 0;
    } else if (i == 1 && rx[1] != 0x59) {
      i = 0;
    } else if (i == 8) {
      for (j = 0; j < 8; j++) {
        checksum += rx[j];
      }
      if (rx[8] == (checksum % 256)) {
        *distance2 = rx[2] + rx[3] * 256;
        *strength2 = rx[4] + rx[5] * 256;

        *complete2 = true;
      }
      i = 0;
    } else {
      i++;

    }
  }
}

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

}

void loop() {
  Serial.println("test");
  // if(receiveComplete1, receiveComplete2) {
  //if ((receiveComplete1 = false) && (receiveComplete2 = false)){
  Serial.print(distance1);
  Serial.print("cm\t");
  Serial.print("strength: ");
  Serial.println(strength1);
  Serial.println("test2");

  Serial.print(distance2);
  Serial.print("cm\t");
  Serial.print("strength: ");
  // Serial.println(strength2);
  Serial.println("test3");
  //  }

}


void serialEvent() {
  getTFminiData1(&distance1, &strength1, &receiveComplete1);
  getTFminiData2(&distance2, &strength2, &receiveComplete2);
  Serial.println("test4");
}

Question: Why are ‘distance1’ and ‘distance2’ not being displayed as measured by the TFMini (It Srial.prints 0cm and Strength 0 in all cases) ? Once I get them to display I can then apply calculations to them to calculate speed (change in distance with time) but that comes later. For now please help: How do I obtain the output for distance1 and distance2 that read proper values not just 0cm all the time.

Neither of the sketches posted have variables named distance1 or distance2 in them

Did you perhaps post the wrong sketch ?

Hi, Thanks for pointing this out. I have changed it now. I had accidentally posted the same code twice. I have the relevant code in there now. Thanks.

The first thing that I would suggest is getting rid of the serialEvent() function as it provides no functionality that you cannot write in a more obvious way by simply using Serial.available() in loop()

Secondly, you have no defined time gap between reading distance1 and distance2. There will be a small time gap because of the of the time that the functions to get the values take to run but it is not under your direct control

Thirdly, you don’t need two getTFminiData functions. You could use one and pass parameters to it

More fundamentally I believe that you have gone about getting two values to compare in an odd way. A more conventional approach would be to take a reading and save it in a variable as the previous reading. After a user defined time take a second reading and compare it with the stored value and save the new reading as the previous reading ready for next time

If the taking of a reading is triggered by an external source you can use the same principle without the user defined time between readings. As it is now you get a single byte via Serial and immediately take two readings. That does not sound right

Thank you. Would you be able to point me to example code that might achieve this please?

Another question (perhaps unrelated) is why is there a send (white) cable to the TFmini IR sensor. I understand the green cable which takes data from the TFMini for processing in Arduino etc - For example I take the green cable from TFMini and put it into the RX serial port on my Arduino, but are there examples of when data is sent to the sensor (TX) also ?

A simple example of the principal of what I described. If the input changes it is reported and saved ready to test for another change

byte currentData;
byte previousData;

void setup()
{
  Serial.begin(115200);
  while (!Serial);
}

void loop()
{
  if (Serial.available())
  {
    currentData = Serial.read();
    if (currentData != previousData)
    {
      Serial.print("changed input : ");
      Serial.println(currentData);
      previousData = currentData;
    }
  }
}

Set the Serial monitor to No line ending and enter a single digit 0 to 9 and press return. If you enter the same digit twice or more in succession you will not get a message in the Serial monitor but enter a different one and you will

As to your other query, you can change some parameters of the sensor by sending commands to it, hence the 2 way serial interface

Hi UKHeliBob, Thanks for this. I was going to change my code on an iterative basis to see what effect each change would have. This also explains why I use a lot of Serial.print commands (test1, 2, A, B etc) to understand the SEQUENCE that the code is executed in. I am using boolean true and false and your suggestion of currentreading/previous reading to try and isolate a reading from its previous one. I still get values of 0 for distance1 and distance 2 and for strength2 and strength2. What would be my next step (starting with the code I have below) to start getting non-zero output in the serial monitor? I think you for the learning!

//#include <SoftwareSerial.h>  //header file of software serial port


//SoftwareSerial Serial1 (2,3); //define software serial port name as Serial1 and define pin2 as RX and pin3 as TX

byte currentData;
byte previousData;

int distance1 = 0;
int strength1 = 0;
boolean receiveComplete1 = false;

int distance2 = 0;
int strength2 = 0;
boolean receiveComplete2 = false;

void getTFminiData1(int* distance1, int* strength1, boolean* complete1) {
  Serial.println("A");
  static char i = 0;
  char j = 0;
  int checksum = 0;
  static int rx[9];
  if (Serial.available()) {
    rx[i] = Serial.read();
    if (rx[0] != 0x59) {
      i = 0;
    } else if (i == 1 && rx[1] != 0x59) {
      i = 0;
    } else if (i == 8) {
      for (j = 0; j < 8; j++) {
        checksum += rx[j];
      }
      if (rx[8] == (checksum % 256)) {
        *distance1 = rx[2] + rx[3] * 256;
        *strength1 = rx[4] + rx[5] * 256;

        *complete1 = true;
      }
      i = 0;

    } else {
      i++;
delay(10);
    }
  }
}

void getTFminiData2(int* distance2, int* strength2, boolean* complete2) {
  Serial.println("B");
  static char m = 0;
  char n = 0;
  int checksum = 0;
  static int rx[9];
  if (Serial.available()) {
    rx[m] = Serial.read();
    if (rx[0] != 0x59) {
      m = 0;
    } else if (m == 1 && rx[1] != 0x59) {
      m = 0;
    } else if (m == 8) {
      for (n = 0; n < 8; n++) {
        checksum += rx[n];
      }
      if (rx[8] == (checksum % 256)) {
        *distance2 = rx[2] + rx[3] * 256;
        *strength2 = rx[4] + rx[5] * 256;

        *complete2 = true;
      }
      m = 0;
    } else {
      m++;
delay(10);
    }
  }
}

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

}

void loop() {
 
  if (Serial.available())
  {
    currentData = Serial.read();
    if (currentData != previousData)
    {
      Serial.print("changed input : ");
      Serial.println(currentData);
           Serial.println(previousData);
    //  Serial.print ("subtracted:  ");Serial.println (currentData-previousData);
      previousData = currentData;
   
    }
  }
  
  Serial.println("test");
  //if(receiveComplete1, receiveComplete2) {
  if ((receiveComplete1 = true) && (receiveComplete2 = true)){
  Serial.print(distance2);
  Serial.print("cm\t");
  Serial.print("strength: ");
  Serial.println(strength2);
  Serial.println("test2");

  Serial.print(distance1);
  Serial.print("cm\t");
  Serial.print("strength: ");
  Serial.println(strength1);
  Serial.println("test3");

  receiveComplete1 = false;
  receiveComplete2 = false;

}
}

void serialEvent() {
  getTFminiData1(&distance1, &strength1, &receiveComplete1);
  getTFminiData2(&distance2, &strength2, &receiveComplete2);
  Serial.println("test4");
}
  

Why have you still got the serialAvent() function in your sketch ? The principle that I am suggesting you use would go something like this

start of loop()
  if Serial data is available
    call readData function to get current data
    if complete is true //all current data has been received
      distance moved = currentDistance minus previousDistance
      //do what you like with the distance moved
      previousDistance = currentDistance  //save for next comparison
    end if
  end if
end of loop()

void readData(&currentDistance, &currentStrength, &complete) //note pass by reference
  //code here to populate currentDistance, currentStrength and complete
end of readData