budryerson / TFMini-Plus-I2C

Arduino library for the Benewake TFMini-Plus LiDAR distance sensor in I2C communication mode
27 stars 16 forks source link

When triggering acquisition externally, sensor locks up if there is no target #20

Closed digamesystems closed 2 years ago

digamesystems commented 2 years ago

Thanks for the spiffy library!

I'm using a pair of TFMini-Ss to measure the direction of travel in a vehicle counting application.

In your example code, the sensor is set up with a frame rate of something like 50 Hz, if I recall correctly. When running in the mode where it is triggering its own acquisition, it functions properly.

I wanted to experiment with running the sensor in an externally triggered mode to see if I can save power. (With internally-controlled acquisition it seems to be running all the time and averaging readings together for reporting at the target rate.)

Turns out that works. -- Setting the frame rate to FRAME_0 and using the TRIGGER_DETECTION function uses about half the power at 50Hz in my bench setup.

When I took the sensor outside and pointed it at the sky, it immediately responded with a tfmP.status of TFMP_WEAK which you would expect. However, from then on, that's all it would respond with even if you point it at a nearby target. tfmP.getData returns false from then on and the tfmP.status result never changes again until a power cycle.

In contrast, when running self-triggered, with FRAME_50, it hands back a status of TFMP_WEAK when looking up, but immediately recovers when you point it at a nearby target.

A bit of my setup code:

  // Send some example commands to the TFMini-Plus
  // - - Perform a system reset - - - - - - - - - - -

  if( tfmP.sendCommand( SOFT_RESET, 0, lidar_1_addr)) { retVal = true; }
  else { return false;}  

  if( tfmP.sendCommand( SOFT_RESET, 0, lidar_2_addr)) { retVal = true; }
  else { return false;}  

  tfmP.sendCommand( SET_FRAME_RATE, FRAME_0, lidar_1_addr);
  tfmP.sendCommand( SET_FRAME_RATE, FRAME_0, lidar_2_addr);

  // using this with FRAME_0 and triggered operation
  if( tfmP.sendCommand( TRIGGER_DETECTION, 0, lidar_1_addr) != true) {
    DEBUG_PRINTLN("Trouble Triggering LIDAR 1");
  }

  if( tfmP.sendCommand( TRIGGER_DETECTION, 0, lidar_2_addr) != true) {
    DEBUG_PRINTLN("Trouble Triggering LIDAR 2");
  }

Acquisition performs a getData call and then triggers the next acquisition. (There is an appropriate delay in the main loop of the program to keep the calls at 50Hz.)

if( tfmP.getData( tfDist, tfFlux, tfTemp, lidar_1_addr)) { 
    dist1 = tfDist;
  } else {  
    dist1 = 1300;  // infinity
    return false; 
  }

...

  // Trigger sensor for the next time around
  if( tfmP.sendCommand( TRIGGER_DETECTION, 0, lidar_1_addr) != true) {
    DEBUG_PRINTLN("Trouble Triggering LIDAR 1");
  }

Any suggestions would be greatly appreciated.

budryerson commented 2 years ago

I understand you to say that neither a SOFT_RESET nor a HARD_RESET nor another command will unlock the device, and that only a power cycle will unlock it. I will try to duplicate the problem as soon as I can. Thanks.

digamesystems commented 2 years ago

I tried using your i2c recovery routines but didn't try the reset routines. I'll give them a try and let you know how it goes.

Thanks.

Sent from my Galaxy Tab A

-------- Original message -------- From: Bud Ryerson @.> Date: 6/18/22 3:02 PM (GMT-08:00) To: budryerson/TFMini-Plus-I2C @.> Cc: "john.price digamesystems.com" @.>, Author @.> Subject: Re: [budryerson/TFMini-Plus-I2C] When triggering acquisition externally, sensor locks up if there is no target (Issue #20)

I understand you to say that neither a SOFT_RESET nor a HARD_RESET nor another command will unlock the device, and that only a power cycle will unlock it. I will try to duplicate the problem as soon as I can. Thanks.

— Reply to this email directly, view it on GitHubhttps://github.com/budryerson/TFMini-Plus-I2C/issues/20#issuecomment-1159572050, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAAUY6WRH2DNMQNYNHQZQ63VPZBPHANCNFSM5ZE645HA. You are receiving this because you authored the thread.Message ID: @.***>

digamesystems commented 2 years ago

Update:

If I issue a SOFT_RESET every time it locks up after a TFMP_WEAK status is returned, it will recover for the next cycle. However, if it's still looking off into space, it will lock on the next command and needs another reset to continue.

If a target is in the field after a reset, it runs normally.

The reset routine takes some time to execute (about 500 msec), so I'm a bit concerned about catching cars coming into the field reliably if the counter is set up in an environment where it's continuously recovering.

Are there other commands you'd recommend looking into?

I'll put together a minimal example program that reproduces the issue for you in the A.M.

Thanks for the help.

budryerson commented 2 years ago

Does it have to run at 50Hz? I ask because the device offers a" low power consumption mode," but the frame rate can't be more than 10Hz when that mode is active. Interestingly, when the flux (signal strength) falls below 100, the device returns a distance of 65535 (-1), a value that my library uses to create an error flag. There's a command to have the device return a different value, say 1200cm. I don't know whether that would make any difference because I didn't build the thing and I don't know why it's (apparently) locking up. Have you tried contacting Benewake? They are usually satisfyingly responsive.

digamesystems commented 2 years ago

Issue Resolved. -- "Pilot error" on my part.

After putting together a little example program to help us debug what the differences were between the two operating modes, I was surprised when my example never locked up.

https://github.com/digamesystems/test_tfmpi2c_trigger (Handy for looking at the difference between power consumption in triggered vs. untriggered modes)

'Turns out in my original application, I was exiting the acquisition routine early whenever I encountered a 'false' return from getData, resulting in my never triggering the next reading.

Sorry for the false alarm!

The offending code:

// Read the LIDAR Sensors
  if( tfmP.getData( tfDist, tfFlux, tfTemp, lidar_1_addr)) { 
    dist1 = deGlitch1(tfDist);
  } else {   
    dist1 = 1300;  // "Infinity".  
    return false;  **** We exit here, never getting to the code below that triggers the next reading! ****
  }

**** OTHER PROCESSING IN HERE... ****

  // Trigger sensor for the next time around **** Note we never get here if the call to getData above fails! ****

  if( tfmP.sendCommand( TRIGGER_DETECTION, 0, lidar_1_addr) != true) {
    DEBUG_PRINTLN("Trouble Triggering LIDAR 1");
  }

Developing software is an exercise in self-discovery. 99 times out of a hundred, the issue is with what you have done to yourself!

Thanks again for the help. Feel free to close this one out.

budryerson commented 2 years ago

You're welcome. Come back anytime.