Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 6 of 6

Thread: Is #include "printf.h" compatible with T 3.5?

  1. #1
    Senior Member
    Join Date
    Dec 2016
    Location
    Buena Park ca
    Posts
    112

    Is #include "printf.h" compatible with T 3.5?

    I got this lidar, TF Mini Plus and found a library for it.

    https://github.com/budryerson/TFMini-Plus


    I have been using Serial.printf for a long time and it required no library, but this sketch must have it.

    I am not able to print anything from the serial port other than my code "NOW" that I added for testing....

    I am on Com 4

    Please help,

    Code:
    #include <TFMPlus.h>  // Include TFMini Plus Library v1.4.1
    TFMPlus tfmP;         // Create a TFMini Plus object
    
    #include "printf.h"   
                                        
    void setup()
    {
        Serial.begin( 115200);   // Intialize terminal serial port
           Serial.println ("NOW");
        delay(20);               // Give port time to initalize
        printf_begin();          // Initialize printf.
        printf("\r\nTFMPlus Library Example - 18JUN2020\r\n");  // say 'hello'
    
        Serial4.begin( 115200);  // Initialize TFMPLus device serial port.
        delay(20);               // Give port time to initalize
        tfmP.begin( &Serial4);   // 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( "System reset: ");
        if( tfmP.sendCommand( SYSTEM_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( OBTAIN_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();
        // - - - - - - - - - - - - - - - - - - - - - - - -
    
        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:%2iC",  tfTemp);   // display temperature,
          printf( "\r\n");                   // end-of-line.
        }
        else                  // If the command fails...
        {
          tfmP.printFrame();  // display the error and HEX dataa
        }
    }
    Thanks

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,746
    Just change all those printf to Serial.printf.

  3. #3
    Senior Member
    Join Date
    Dec 2016
    Location
    Buena Park ca
    Posts
    112
    Great that worked,

    So for everyone else in the teensy family this should go like

    Code:
    #include <TFMPlus.h>  // Include TFMini Plus Library v1.4.1
    TFMPlus tfmP;         // Create a TFMini Plus object
    
    #include "printf.h"   
                                        
    void setup()
    {
        Serial.begin( 115200);   // Intialize terminal serial port
           Serial.println ("NOW");
        delay(20);               // Give port time to initalize
        printf_begin();          // Initialize printf.
        Serial.printf("\r\nTFMPlus Library Example - 18JUN2020\r\n");  // say 'hello'
    
        Serial4.begin( 115200);  // Initialize TFMPLus device serial port.
        delay(20);               // Give port time to initalize
        tfmP.begin( &Serial4);   // Initialize device library object and...
                                 // pass device serial port to the object.
    
        // Send some example commands to the TFMini-Plus
        // - - Perform a system reset - - - - - - - - - - -
        Serial.printf( "System reset: ");
        if( tfmP.sendCommand( SYSTEM_RESET, 0))
        {
            Serial.printf( "passed.\r\n");
        }
        else tfmP.printReply();
      
        delay(500);  // added to allow the System Rest enough time to complete
    
      // - - Display the firmware version - - - - - - - - -
        Serial.printf( "Firmware version: ");
        if( tfmP.sendCommand( OBTAIN_FIRMWARE_VERSION, 0))
        {
            Serial.printf( "%1u.", tfmP.version[ 0]); // print three single numbers
            Serial.printf( "%1u.", tfmP.version[ 1]); // each separated by a dot
            Serial.printf( "%1u\r\n", tfmP.version[ 2]);
        }
        else tfmP.printReply();
        // - - Set the data frame-rate to 20Hz - - - - - - - -
        Serial.printf( "Data-Frame rate: ");
        if( tfmP.sendCommand( SET_FRAME_RATE, FRAME_20))
        {
            Serial.printf( "%2uHz.\r\n", FRAME_20);
        }
        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.
        {
          Serial.printf( "Dist:%04icm ", tfDist);   // display distance,
          Serial.printf( "Flux:%05i ",   tfFlux);   // display signal strength/quality,
          Serial.printf( "Temp:%2iC",  tfTemp);   // display temperature,
          Serial.printf( "\r\n");                   // end-of-line.
        }
        else                  // If the command fails...
        {
          tfmP.printFrame();  // display the error and HEX dataa
        }
    }

  4. #4
    Senior Member
    Join Date
    Dec 2016
    Location
    Buena Park ca
    Posts
    112
    I integrated the Lidar read in my robot general sketch and each reading is blocking it horribly.
    Whether I read at 10 hz or 100, all my processes stop at each read.
    The library author says
    "The TFMini-Plus is transmitting serial data asynchronously at the data frame-rate. The TFMP library flushes the serial buffer at every getData to ensure that the data read is timely. "

    I am using UART 8. Is there any point in moving it to another serial? are some of the UART ports buffered inside the Teensy 4.1?

    Is there a better way to write this reading of the lidar?
    I heard of multi threading, but its beyond my understanding... Would that help?

    Thanks a lot
    Mitch

  5. #5
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,664
    The hardware on all hardware UARTS on Teensy 4.x are the same. So probably not much to do there.

    But I am not sure the underlying code is written in a way that I would write it... That is if you are calling the code:
    Code:
    bool TFMPlus::getData( int16_t &dist, int16_t &flux, int16_t &temp)
    {
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // Step 1 - Get data from the device.
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // Set timer to one second timeout if HEADER never appears
        // or serial data never becomes available.
        uint32_t serialTimeout = millis() + 1000;
        
        // Flush all but last frame of data from the serial buffer.
        while( (*pStream).available() > TFMP_FRAME_SIZE) (*pStream).read();
    
    	  // Zero out the entire frame data buffer.
        memset( frame, 0, sizeof( frame));
    
        // Read one byte from the serial buffer into the last byte of
        // the frame buffer, then left shift the whole array one byte.
        // Repeat until the two HEADER bytes show up as the first
        // two bytes in the array.
        while( ( frame[ 0] != 0x59) || ( frame[ 1] != 0x59))
        {
            if( (*pStream).available())
            {
                // Read one byte into the framebuffer's
                // last plus one position.
                frame[ TFMP_FRAME_SIZE] = (*pStream).read();
                // Shift the last nine bytes one byte left.
                memcpy( frame, frame + 1, TFMP_FRAME_SIZE);
            }
            // If HEADER or serial data are not available
            // after more than one second...
            if( millis() >  serialTimeout)
            {
                status = TFMP_HEADER;   // then set error...
                return false;           // and return "false".
            }
        }
    ...
    That is this code more or less guarantees that you will toss out all full packets and then wait at the baud rate speed for some portion of the current packet to be received (or timeout)...

    Also I am not sure I would code this where I read in the data after the size of the packet and memcpy the data down... But that is me...

    Also you may run into issues where are software FIFO queue for the Software Serial port fills up, and I don't remember if we toss the old stuff or lose the new stuff.
    I believe we toss the new stuff...

  6. #6
    Senior Member
    Join Date
    Dec 2016
    Location
    Buena Park ca
    Posts
    112
    Great observations Kurt,

    I moved the mode of the lidar to IC2, no more interference,

    running at 400KHZ

    For the teensy community , here is the library

    https://github.com/budryerson/TFMini-Plus

    Dont bother with serial.


    To configure the device for I2C communication, a command must be sent either by using this library's SET_I2C_MODE command or the serial GUI test application and code supplied by the manufacturer (see attached Product Manual).

    The SET_I2C_MODE command does not require a subsequent SAVE_SETTINGS command. The device will remain in I2C mode after power has been removed and restored. The only way to return to serial mode is with the SET_SERIAL_MODE command. Even a RESTORE_FACTORY_SETTINGS command will NOT restore the device to its default, UART communication interface mode.

    The device functions as an I2C slave device and the default address is 16 (0x10 Hex) but is user-programable by sending the SET_I2C_ADDRESS command and a parameter in the range of 1 to 127. The new setting will take effect immediately without a SAVE_SETTINGS command, however the RESTORE_FACTORY_SETTINGS command will restore the default address. The I2C address can be changed and set while still in serial communication mode. Or if in I2C mode, the example sketch included in the TFMini-Plus-I2C library can be used to test and change the address.


    Teensy forever.
    YEY

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •