Issue switching to I2C mode for TFMini-Plus-I2C

Hi, I am attempting to set up a TFMini-Plus (a LIDAR sensor) to run using the I2C protocol but have been unsuccessful in getting it to switch from UART to I2C (Note: The sensor works fine in SERIAL/UART mode). I am motivated to switch to I2C because I plan to run 8 of these simultaneously on a Mega board. My setup is as follows:

  1. Arduino Mego 2560 board
  2. Logic Level Converter to get 3.3V to the SDA and SCL ports of the TFMiniPlus

I have attempted a few different things, but my goal would be to switch these sensors using the Arduino Mega itself, as I run on a mac and cannot use the provided GUI from Benewake. I have recently tried sending the SET_I2C_MODE with the sendCommand function from Bud Ryerson's TFMini-Plus-I2C Arduino library. This returns as a fail in my script. My script is attached below. I am happy to provide more details or try other things out.

Thank you for all your time and any assistance you may be able to give me!

#include <Wire.h>
#include <TFMPI2C.h>
TFMPI2C tfmP;

void set_i2c_mode()
{

    if( tfmP.sendCommand( SET_I2C_MODE, 0 ))
    {
        // If successful, display "complete"
        Serial.print( "Complete");   
    }
    else
    {
        // If not successful, display the attempt number
        Serial.print( "failed. "); 
      
    }
    delay(100);
}

void setup() {
  Serial.begin( 115200);   // Initialize terminal serial port
  delay(20);
  Serial.flush();          // Flush serial write buffer
  while( Serial.available())Serial.read();  // flush serial read buffer

  Serial.println();
  Serial.println( "*****************************");
  Serial.println( "Issue command to switch to I2C");
  set_i2c_mode();
}

void loop() {}

I have also tried using the provided example scripts in the TFMini-Plus-I2C library. Here is the output I receive from the TMFPI2C_example.ino case.

TFMPlus I2C Library Example - 14JAN2022

Recover default I2C bus.
System reset:  Status: I2C-WRITE 00 00 00 00 00 00 00 00
Firmware version:  Status: I2C-WRITE 00 00 00 00 00 00 00 00
Data-Frame rate:  Status: I2C-WRITE 00 00 00 00 00 00 00 00
Set Serial Mode:  Status: I2C-WRITE 00 00 00 00 00 00 00 00
Save Settings:  Status: I2C-WRITE 00 00 00 00 00 00 00 00
 Status: I2C-WRITE Data: 00 00 00 00 00 00 00 00 00
Recover default I2C bus.
 Status: I2C-WRITE Data: 00 00 00 00 00 00 00 00 00
Recover default I2C bus.
 Status: I2C-WRITE Data: 00 00 00 00 00 00 00 00 00

What is that? Please post a link.

It is a LIDAR sensor. I tried adding a link but the post got flagged. You can google TFMini-Plus-I2C to see what I am talking about.

Hi @bornhoft. I apologize for the inconvenience.

I have added sparkfun.com to the forum's "allow list" in order to prevent this from happening again in the future. You should now be able to post the link without problems.

The forum's automated spam filter sometimes produces false positives, which result in those topics temporarily being hidden unjustly. This is why a team of human moderators review every action taken by the automated system.

So I think in the end these false detections are always corrected, but there is an unfortunate delay between the time of the spam detection and when a moderator reviews the action.

3 Likes

Is it necessary to connect to the sensor using UART in order to switch it to i²c mode? If so, how does your sketch above achieve that?

If not, is the sensor detected by the i²c scanner sketch (from examples menu) when connected to the i2c bus?

EDIT: from your GitHub link above:

The command to configure the device for I2C communication must be sent using the UART interface.

I don't see how your sketch above can be doing that. The library you are using seems to be i²c only, it doesn't appear to be capable of using UART to communicate to the sensor, and that is necessary to switch to i²c mode.

Can you try to post the link again? I've found data sheet for TFmini Plus, but there's no mention of i2c in it. I've found data sheet for TFmini i²c, but not TFmini Plus i²c.

Can you try to post the link again?

Sure thing. Here is a data sheet for the i2c version of the sensor

Have you tried communicating between the Mega and a sensor using UART yet? You said you had that working but I don't know if you meant with the Mega or direct to the pc.

The necessary command to put the device into i²c mode is here:


This describes the data to be sent in more detail:

@PaulRB, thanks for the comments and directions.

The library you are using seems to be i²c only, it doesn't appear to be capable of using UART to communicate to the sensor, and that is necessary to switch to i²c mode.

You are correct! I was only using a library that uses I2C. After your comments, I looked a bit closer at the available libraries. There are two libraries developed by Bud Ryerson. The first is TFMini-Plus_I2C, the second is TFMini-Plus. This second library is the appropriate one to use when in UART mode and it can also be used to switch the sensor to I2C mode. The first library is specifically for I2C communication (as you correctly point out) and can be used to switch the sensor back to UART mode. I am attaching the script I used (which is only slightly modified from the original example provided by Bud Ryerson) to switch the mode of the sensor. I had the green wire (TX) connected to output 11 and the white wire (RX) connected to output 10 of an Arduino Mega board.

Have you tried communicating between the Mega and a sensor using UART yet? You said you had that working but I don't know if you meant with the Mega or direct to the pc.

I was able to connect using UART, but only with the Mega directly. I don't believe there is a way to connect the sensor directly to a MacOS, but I could be wrong on that point.

Either way, your questions, and comments have led me to a solution! Thanks so much for your help!

/* File Name: TFMP_example.ino
 * Developer: Bud Ryerson
 * Inception: 29JAN2019
 * Last work: 10SEP2021
 * Description: Arduino sketch to test the Benewake TFMini Plus
 * time-of-flight Lidar ranging sensor using the TFMPlus Library.
 * Default settings for the TFMini Plus are a 115200 serial baud rate
 * and a 100Hz measurement frame rate. The device will begin returning
 * measurement data right away:
 *   Distance in centimeters,
 *   Signal strength in arbitrary units,
 *   and an encoded number for Temperature in degrees centigrade.
 * Use the 'sendCommand()' to send commands and return a status code.
 * Commands are selected from the library's list of defined commands.
 * Parameters can be entered directly (115200, 250, etc) but for
 * safety, they should be chosen from the library's defined lists.
 */

#include <TFMPlus.h>  // Include TFMini Plus Library v1.5.0
TFMPlus tfmP;         // Create a TFMini Plus object

#include "printf.h"   // Modified to support Intel based Arduino
                      // devices such as the Galileo. Download from:
                      // https://github.com/spaniakos/AES/blob/master/printf.h

// The Software Serial library is an alternative for devices that
// have only one hardware serial port. Delete the comment slashes
// on lines 37 and 38 to invoke the library, and be sure to choose
// the correct RX and TX pins: pins 10 and 11 in this example. Then
// in the 'setup' section, change the name of the hardware 'Serial2'
// port to match the name of your software serial port, such as:
// 'mySerial.begin(115200); etc.

#include <SoftwareSerial.h>       
SoftwareSerial mySerial( 10, 11);   
                                    
void setup()
{
    Serial.begin( 115200);   // Intialize terminal serial port
    delay(20);               // Give port time to initalize
    printf_begin();          // Initialize printf.
    printf("\r\nTFMPlus Library Example - 10SEP2021\r\n");  // say 'hello'

    mySerial.begin( 115200);  // Initialize TFMPLus device serial port.
    delay(20);               // Give port time to initalize
    tfmP.begin( &mySerial);   // Initialize device library object and...
                             // pass device serial port to the object.

    // Send some example commands to the TFMini-Plus
    // - - Perform a system reset - - - - - - - - - - -
    printf( "Soft reset: ");
    if( tfmP.sendCommand( SOFT_RESET, 0))
    {
        printf( "passed.\r\n");
    }
    else tfmP.printReply();
  
    delay(500);  // added to allow the System Rest enough time to complete

  // - - Display the firmware version - - - - - - - - -
    printf( "Firmware version: ");
    if( tfmP.sendCommand( GET_FIRMWARE_VERSION, 0))
    {
        printf( "%1u.", tfmP.version[ 0]); // print three single numbers
        printf( "%1u.", tfmP.version[ 1]); // each separated by a dot
        printf( "%1u\r\n", tfmP.version[ 2]);
    }
    else tfmP.printReply();
    // - - Set the data frame-rate to 20Hz - - - - - - - -
    printf( "Data-Frame rate: ");
    if( tfmP.sendCommand( SET_FRAME_RATE, FRAME_20))
    {
        printf( "%2uHz.\r\n", FRAME_20);
    }
    else tfmP.printReply();
    // - - - - - - - - - - - - - - - - - - - - - - - -

  // - - - - - - - - - - - - - - - - - - - - - - - -  
    // The next two commands may be used to switch the device 
    // into I2C mode.  This sketch will no longer receive UART
    // (serial) data.  The 'TFMPI2C_example' sketch in the 
    // TFMPI2C Library can be used to switch the device back
    // to UART mode.
    // Don't forget to switch the cables, too.
    // - - - - - - - - - - - - - - - - - - - - - - - -
    printf( "Set I2C Mode: ");
    if( tfmP.sendCommand( SET_I2C_MODE, 0))
    {
        printf( "mode set.\r\n");
    }
    else tfmP.printReply();
    printf( "Save settings: ");
    if( tfmP.sendCommand( SAVE_SETTINGS, 0))
    {
        printf( "saved.\r\n");
    }
    else tfmP.printReply();
    // - - - - - - - - - - - - - - - - - - - - - - - -    


  delay(500);            // And wait for half a second.
}

// Initialize variables
int16_t tfDist = 0;    // Distance to object in centimeters
int16_t tfFlux = 0;    // Strength or quality of return signal
int16_t tfTemp = 0;    // Internal temperature of Lidar sensor chip

// Use the 'getData' function to pass back device data.
void loop()
{
    delay(50);   // Loop delay to match the 20Hz data frame rate

    if( tfmP.getData( tfDist, tfFlux, tfTemp)) // Get data from the device.
    {
      printf( "Dist:%04icm ", tfDist);   // display distance,
      printf( "Flux:%05i ",   tfFlux);   // display signal strength/quality,
      printf( "Temp:%2i%s",  tfTemp, "C");   // display temperature,
      printf( "\r\n");                   // end-of-line.
    }
    else                  // If the command fails...
    {
      tfmP.printFrame();  // display the error and HEX dataa
    }
}

Are you sure that's what you posted? The code in post #9 looks like it's i²c only, like the previous sketches you posted. It could be useful for others using this sensor in future to see the code you used to switch communications mode and set the i²c address.

Are you sure that's what you posted?

@PaulRB, good catch. I have updated the post above. Thanks!

Note for others reading this topic in the future:

It's a minor point and doesn't really matter in this particular case, but , unlike Uno, Nano etc, Mega has several available/unused hardware serial (UART) ports, which should be used in preference to software serial.

I guess this sketch will have been written to work on either Uno or Mega, and that's why it uses software serial. In this case it will only be used briefly, once, to change the sensor to i²c mode.

For others reading this topic in the future, if you plan to use one or even two or three of these sensors with serial/UART communications rather than i²c, always use the available hardware serial (UART) ports.

@bornhoft could you have used the above code to change to i²c mode and set the i²c address at the same time? I suspect if you set the new address before saving the settings, that might work and would save time later, as of course you can't connect multiple devices on the i²c bus at the same time with the same address.

@PaulRB, these are all great points that you made above. I will clean up the script, add the address change, and post it here when completed. These are all things that need to be done anyways as I have to change eight of these sensors.