ModalAI Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    How to use UART in custom applications

    Software Development
    2
    8
    230
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Samuel LehmanS
      Samuel Lehman
      last edited by

      I am currently trying to make a simple application that gets imu data and sends it out through uart. I am using the voxl-cross-template project as a base for this application. I have tried using some of the code in the libqrb5165-io project to get the uart to work however I have been unable to compile it. I believe it might be an issue with my cmake files.

      [ 50%] Linking C executable hello-cross
      CMakeFiles/hello-cross.dir/main.c.o: In function `_helper_cb':
      main.c:(.text+0xb8): undefined reference to `voxl_uart_write'
      main.c:(.text+0xfc): undefined reference to `ERROR'
      CMakeFiles/hello-cross.dir/main.c.o: In function `main':
      main.c:(.text.startup+0x3c): undefined reference to `voxl_uart_init'
      main.c:(.text.startup+0xcc): undefined reference to `voxl_uart_close'
      main.c:(.text.startup+0xec): undefined reference to `ERROR'
      main.c:(.text.startup+0x100): undefined reference to `ERROR'
      collect2: error: ld returned 1 exit status
      src/CMakeFiles/hello-cross.dir/build.make:99: recipe for target 'src/hello-cross' failed
      make[2]: *** [src/hello-cross] Error 1
      CMakeFiles/Makefile2:97: recipe for target 'src/CMakeFiles/hello-cross.dir/all' failed
      make[1]: *** [src/CMakeFiles/hello-cross.dir/all] Error 2
      Makefile:135: recipe for target 'all' failed
      make: *** [all] Error 2
      starting building Debian Package
      mkdir: cannot create directory 'pkg/DEB': No such file or directory
      
      

      Is there a better way to send data out through uart? Is there an example of something similar to what I'm trying to do out there that I can look at?

      Here is my current main function and helper_cb for reference:

      int main(int argc, char *const argv[])
      {
      
          enable_signal_handler();
          main_running = 1;
      
          int uart_res = voxl_uart_init(device, baud, 1.0, 0, 1, 0);
          if (uart_res < 0)
          {
              ERROR("Failed to open port");
              resurn 1;
          }
      
          pipe_client_set_simple_helper_cb(0, _helper_cb, NULL);
          pipe_client_set_disconnect_cb(0, _disconnect_cb, NULL);
      
          int pipe_open_res = pipe_client_open(0, imu_name, CLIENT_NAME,
                                               EN_PIPE_CLIENT_SIMPLE_HELPER,
                                               IMU_RECOMMENDED_READ_BUF_SIZE);
      
          if (pipe_open_res < 0)
          {
              pipe_print_error(pipe_open_res);
              printf(ENABLE_WRAP);
              return -1;
          }
      
          // keep going until the  signal handler sets the running flag to 0
          while (main_running)
              usleep(500000);
      
          // all done, signal pipe read threads to stop
          printf("\nclosing and exiting\n" RESET_FONT ENABLE_WRAP);
          pipe_client_close_all();
      
          int ret = voxl_uart_close(device);
          if (ret < 0)
          {
              ERROR("Failed to close UART device");
              return 1;
          }
      }
      static void _helper_cb(__attribute__((unused)) int ch, char *data, int bytes, __attribute__((unused)) void *context)
      {
      
          const uint8_t MIN_WRITE_LEN = 32;
          uint8_t write_buf[MIN_WRITE_LEN];
      
          // validate that the data makes sense
          int n_packets;
          imu_data_t *data_array = pipe_validate_imu_data_t(data, bytes, &n_packets);
          if (data_array == NULL)
              return;
      
          // print everything in one go.
          if (!en_newline)
              printf("\r" CLEAR_LINE);
          printf("%7.2f|%7.2f|%7.2f|%7.2f|%7.2f|%7.2f",
                 (double)data_array[n_packets - 1].accl_ms2[0],
                 (double)data_array[n_packets - 1].accl_ms2[1],
                 (double)data_array[n_packets - 1].accl_ms2[2],
                 (double)data_array[n_packets - 1].gyro_rad[0],
                 (double)data_array[n_packets - 1].gyro_rad[1],
                 (double)data_array[n_packets - 1].gyro_rad[2]);
      
          if (en_newline)
              printf("\n");
      
          int write_res = voxl_uart_write(device, write_buf, MIN_WRITE_LEN);
          if (write_res < 0)
          {
              ERROR("Failed to write to UART");
              return;
          }
      
          fflush(stdout);
          return;
      }
      
      Alex KushleyevA 1 Reply Last reply Reply Quote 0
      • Alex KushleyevA
        Alex Kushleyev ModalAI Team @Samuel Lehman
        last edited by

        @Samuel-Lehman ,

        In your application, you should be including <voxl_io.h> and linking against voxl_io library:

        in cmake file:

        target_link_libraries(${app_name} LINK_PUBLIC voxl-io)
        

        Both the header and library (.so) are part of libqrb5165-io package that is built from this project: https://gitlab.com/voxl-public/voxl-sdk/core-libs/libqrb5165-io/

        So, if you are building your app using cross-compiler, make sure to install the libqrb5165-io inside the cross compiler docker before building the application. Typically all our projects have a script for installing build deps, here it is for the libqrb5165-io library (which obviously does not include the library itself as a dependency, because we are actually building it here ) : https://gitlab.com/voxl-public/voxl-sdk/core-libs/libqrb5165-io/-/blob/master/install_build_deps.sh

        You can also just run apt update && apt install libqrb5165-io after you spin up your cross compile docker.

        You can also build your app directly on voxl2, as the libqrb5165-io library should already be installed as part of our SDK.

        Alex

        Samuel LehmanS 1 Reply Last reply Reply Quote 0
        • Samuel LehmanS
          Samuel Lehman @Alex Kushleyev
          last edited by

          @Alex-Kushleyev thank you for your response, however I am still unable to build the project. I have libqrb5165-io added to my install_build_deps.sh and I do have the voxl_io header included in my main file. Maybe I am placing the cmake line in the wrong spot or in the wrong cmake file altogether as I have two of them. Here are the cmake files in my src folder and root folder respectively:

          // ./src/CMakeLists.txt
          
          cmake_minimum_required(VERSION 3.3)
          
          SET(TARGET hello-cross)
          
          # Build from all source files
          file(GLOB all_src_files *.c*)
          
          add_executable(${TARGET}
          	${all_src_files}
          )
          
          
          include_directories(
              ../include
          )
          
          find_library(MODAL_JSON  modal_json  HINTS /usr/lib /usr/lib64)
          find_library(MODAL_PIPE  modal_pipe  HINTS /usr/lib /usr/lib64)
          find_library(VOXL_CUTILS voxl_cutils HINTS /usr/lib /usr/lib64)
          find_library(VOXL_IO libvoxl_io HINTS /usr/lib /usr/lib64)
          
          target_link_libraries(
              ${TARGET}
              pthread
              ${MODAL_JSON}
              ${MODAL_PIPE}
              ${VOXL_CUTILS}
              ${app_name} LINK_PUBLIC voxl-io
          )
          
          # make sure everything is installed where we want
          # LIB_INSTALL_DIR comes from the parent cmake file
          install(
              TARGETS			${TARGET}
          	LIBRARY			DESTINATION ${LIB_INSTALL_DIR}
          	RUNTIME			DESTINATION /usr/bin
          	PUBLIC_HEADER	DESTINATION /usr/include
          )
          
          // ./CMakeLists.txt
          
          cmake_minimum_required(VERSION 3.3)
          
          project(voxl-hello-cross C)
          
          include_directories(
          	"include/"
          )
          
          
          # Strawson's list of standard list of default gcc flags. Yes, I treat
          # warnings as errors. Warnings exist to point out sloppy code and potential
          # failure points for good reason. We do not approve of sloppy code.
          # set(CMAKE_C_FLAGS "-std=gnu99 -Werror -Wall -Wextra -Wuninitialized \
          # 	-Wunused-variable -Wdouble-promotion -Wmissing-prototypes \
          # 	-Wmissing-declarations -Werror=undef -Wno-unused-function ${CMAKE_C_FLAGS}")
          set(CMAKE_C_FLAGS "-std=gnu99 -Wuninitialized \
          	-Wdouble-promotion -Wmissing-prototypes \
          	-Wmissing-declarations -Werror=undef ${CMAKE_C_FLAGS}")
          
          
          # for VOXL, install 64-bit libraries to lib64, 32-bit libs go in /usr/lib
          if(CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
          	set(LIB_INSTALL_DIR /usr/lib64)
          else()
          	set(LIB_INSTALL_DIR /usr/lib)
          endif()
          
          # include each subdirectory, may have others in example/ or lib/ etc
          add_subdirectory (src)
          

          here is the output when I run the install and build scripts:

          using qrb5165 sdk-1.0 debian repo
          Ign:1 http://voxl-packages.modalai.com ./dists/qrb5165/sdk-1.0/binary-arm64/ InRelease
          Ign:2 http://voxl-packages.modalai.com ./dists/qrb5165/sdk-1.0/binary-arm64/ Release
          Get:3 http://voxl-packages.modalai.com ./dists/qrb5165/sdk-1.0/binary-arm64/ Packages [23.2 kB]
          Fetched 23.2 kB in 0s (61.3 kB/s)
          Reading package lists... Done
          installing: 
          libmodal-json
          libmodal-pipe
          libvoxl-cutils
          libqrb5165-io
          
          Reading package lists... Done
          Building dependency tree       
          Reading state information... Done
          libmodal-json:arm64 is already the newest version (0.4.3).
          libvoxl-cutils:arm64 is already the newest version (0.1.1).
          libqrb5165-io:arm64 is already the newest version (0.4.7).
          libmodal-pipe:arm64 is already the newest version (2.10.4).
          0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
          
          Done installing dependencies
          
          -- The C compiler identification is GNU 7.5.0
          -- Detecting C compiler ABI info
          -- Detecting C compiler ABI info - done
          -- Check for working C compiler: /usr/bin/aarch64-linux-gnu-gcc-7 - skipped
          -- Detecting C compile features
          -- Detecting C compile features - done
          CMake Error at src/CMakeLists.txt:22 (target_link_libraries):
            The LINK_PUBLIC or LINK_PRIVATE option must appear as the second argument,
            just after the target name.
          

          Im new to cmake so I have no idea what I am doing.

          Alex KushleyevA 1 Reply Last reply Reply Quote 0
          • Alex KushleyevA
            Alex Kushleyev ModalAI Team @Samuel Lehman
            last edited by Alex Kushleyev

            I think you need to update the target_link_libraries entry to:

            target_link_libraries(
                ${TARGET}
                pthread
                ${MODAL_JSON}
                ${MODAL_PIPE}
                ${VOXL_CUTILS}
                voxl-io
            )
            

            or $(VOXL_IO) instead of voxl-io since you already defined it using:

            find_library(VOXL_IO libvoxl_io HINTS /usr/lib /usr/lib64)
            

            Please try

            Alex

            Samuel LehmanS 1 Reply Last reply Reply Quote 0
            • Samuel LehmanS
              Samuel Lehman @Alex Kushleyev
              last edited by

              @Alex-Kushleyev after adding $(VOXL_IO) i get:

              -- Build files have been written to: /home/root/build
              [ 50%] Building C object src/CMakeFiles/hello-cross.dir/main.c.o
              /home/root/src/main.c: In function '_helper_cb':
              /home/root/src/main.c:88:21: warning: implicit declaration of function 'voxl_uart_write'; did you mean 'voxl_spi_write'? [-Wimplicit-function-declaration]
                   int write_res = voxl_uart_write(device, write_buf, MIN_WRITE_LEN);
                                   ^~~~~~~~~~~~~~~
                                   voxl_spi_write
              /home/root/src/main.c: In function 'main':
              /home/root/src/main.c:105:20: warning: implicit declaration of function 'voxl_uart_init'; did you mean 'voxl_i2c_init'? [-Wimplicit-function-declaration]
                   int uart_res = voxl_uart_init(device, baud, 1.0, 0, 1, 0);
                                  ^~~~~~~~~~~~~~
                                  voxl_i2c_init
              /home/root/src/main.c:134:15: warning: implicit declaration of function 'voxl_uart_close'; did you mean 'voxl_i2c_close'? [-Wimplicit-function-declaration]
                   int ret = voxl_uart_close(device);
                             ^~~~~~~~~~~~~~~
                             voxl_i2c_close
              [100%] Linking C executable hello-cross
              CMakeFiles/hello-cross.dir/main.c.o: In function `_helper_cb':
              main.c:(.text+0xb8): undefined reference to `voxl_uart_write'
              CMakeFiles/hello-cross.dir/main.c.o: In function `main':
              main.c:(.text.startup+0x44): undefined reference to `voxl_uart_init'
              main.c:(.text.startup+0xd0): undefined reference to `voxl_uart_close'
              collect2: error: ld returned 1 exit status
              src/CMakeFiles/hello-cross.dir/build.make:100: recipe for target 'src/hello-cross' failed
              make[2]: *** [src/hello-cross] Error 1
              CMakeFiles/Makefile2:97: recipe for target 'src/CMakeFiles/hello-cross.dir/all' failed
              make[1]: *** [src/CMakeFiles/hello-cross.dir/all] Error 2
              Makefile:135: recipe for target 'all' failed
              make: *** [all] Error 2
              Package Name:  voxl-cross-template
              version Number:  0.0.1
              Consolidate compiler generated dependencies of target hello-cross
              [ 50%] Linking C executable hello-cross
              CMakeFiles/hello-cross.dir/main.c.o: In function `_helper_cb':
              main.c:(.text+0xb8): undefined reference to `voxl_uart_write'
              CMakeFiles/hello-cross.dir/main.c.o: In function `main':
              main.c:(.text.startup+0x44): undefined reference to `voxl_uart_init'
              main.c:(.text.startup+0xd0): undefined reference to `voxl_uart_close'
              collect2: error: ld returned 1 exit status
              src/CMakeFiles/hello-cross.dir/build.make:100: recipe for target 'src/hello-cross' failed
              make[2]: *** [src/hello-cross] Error 1
              
              Alex KushleyevA 1 Reply Last reply Reply Quote 0
              • Alex KushleyevA
                Alex Kushleyev ModalAI Team @Samuel Lehman
                last edited by

                This is odd because the uart function definitions are here :

                https://gitlab.com/voxl-public/voxl-sdk/core-libs/libqrb5165-io/-/blob/master/apps/library/include/voxl_io/uart.h?ref_type=heads#L69

                Are you sure that you are including <voxl_io.h> in your app? implicit declaration of function warning is a clear sign that the function declaration is not found (from voxl_io.h, well actually from voxl_io/uart.h, latter being included from voxl_io.h.

                Please double check.

                Alex

                Samuel LehmanS 1 Reply Last reply Reply Quote 0
                • Samuel LehmanS
                  Samuel Lehman @Alex Kushleyev
                  last edited by

                  @Alex-Kushleyev I have it included, heres my full main file:

                  #include <stdio.h> // for fprintf
                  #include <unistd.h>
                  #include <getopt.h>
                  #include <string.h>
                  #include <modal_pipe.h>
                  #include <voxl_cutils.h>
                  #include <voxl_io.h>
                  #include "hello_cross.h"
                  
                  #define CLIENT_NAME "hello-cross"
                  
                  static char en_newline = 0;
                  static char imu_name[64];
                  static int opt = 0;
                  static int device = 1; // default. /dev/ttyHS1
                  static int baud = 115200;
                  
                  void printHelloCross(void);
                  
                  // called whenever we disconnect from the server
                  static void _disconnect_cb(__attribute__((unused)) int ch, __attribute__((unused)) void *context)
                  {
                      fprintf(stderr, "\r" CLEAR_LINE FONT_BLINK "server disconnected" RESET_FONT);
                      return;
                  }
                  
                  // called when the simple helper has data for us
                  static void _helper_cb(__attribute__((unused)) int ch, char *data, int bytes, __attribute__((unused)) void *context)
                  {
                  
                      const uint8_t MIN_WRITE_LEN = 32;
                      uint8_t write_buf[MIN_WRITE_LEN];
                  
                      // validate that the data makes sense
                      int n_packets;
                      imu_data_t *data_array = pipe_validate_imu_data_t(data, bytes, &n_packets);
                      if (data_array == NULL)
                          return;
                  
                      // print everything in one go.
                      if (!en_newline)
                          printf("\r" CLEAR_LINE);
                      printf("%7.2f|%7.2f|%7.2f|%7.2f|%7.2f|%7.2f",
                             (double)data_array[n_packets - 1].accl_ms2[0],
                             (double)data_array[n_packets - 1].accl_ms2[1],
                             (double)data_array[n_packets - 1].accl_ms2[2],
                             (double)data_array[n_packets - 1].gyro_rad[0],
                             (double)data_array[n_packets - 1].gyro_rad[1],
                             (double)data_array[n_packets - 1].gyro_rad[2]);
                  
                      if (en_newline)
                          printf("\n");
                  
                      int write_res = voxl_uart_write(device, write_buf, MIN_WRITE_LEN);
                      if (write_res < 0)
                      {
                          //ERROR("Failed to write to UART");
                          return;
                      }
                  
                      fflush(stdout);
                      return;
                  }
                  
                  int main(int argc, char *const argv[])
                  {
                  
                      enable_signal_handler();
                      main_running = 1;
                  
                      int uart_res = voxl_uart_init(device, baud, 1.0, 0, 1, 0);
                      if (uart_res < 0)
                      {
                          //ERROR("Failed to open port");
                          return 1;
                      }
                  
                      pipe_client_set_simple_helper_cb(0, _helper_cb, NULL);
                      pipe_client_set_disconnect_cb(0, _disconnect_cb, NULL);
                  
                      int pipe_open_res = pipe_client_open(0, imu_name, CLIENT_NAME,
                                                           EN_PIPE_CLIENT_SIMPLE_HELPER,
                                                           IMU_RECOMMENDED_READ_BUF_SIZE);
                  
                      if (pipe_open_res < 0)
                      {
                          pipe_print_error(pipe_open_res);
                          printf(ENABLE_WRAP);
                          return -1;
                      }
                  
                      // keep going until the  signal handler sets the running flag to 0
                      while (main_running)
                          usleep(500000);
                  
                      // all done, signal pipe read threads to stop
                      printf("\nclosing and exiting\n" RESET_FONT ENABLE_WRAP);
                      pipe_client_close_all();
                  
                      int ret = voxl_uart_close(device);
                      if (ret < 0)
                      {
                          //ERROR("Failed to close UART device");
                          return 1;
                      }
                  }
                  
                  void printHelloCross()
                  {
                      printf("   Imu Acceleration and Gyro\n");
                      printf("   X   |   Y   |   Z   |  X   |   Y   |   Z\n");
                  }
                  
                  Alex KushleyevA 1 Reply Last reply Reply Quote 0
                  • Alex KushleyevA
                    Alex Kushleyev ModalAI Team @Samuel Lehman
                    last edited by Alex Kushleyev

                    @Samuel-Lehman , Not sure what is going on but i was able to build your example with the following command on VOXL2. I had to comment out #include "hello_cross.h" because i did not have it.

                    voxl2:~$ gcc -O2 -Wall voxl_io_uart_test.c -o voxl_io_uart_test -lmodal_pipe -lvoxl_io -L/usr/lib64
                    voxl_io_uart_test.c:14:12: warning: 'opt' defined but not used [-Wunused-variable]
                     static int opt = 0;
                                ^~~
                    voxl2:~$
                    

                    I am not sure what's going on, you can enable verbose CMake file to see what compile command CMake is generating and compare that to the above.

                    Alex

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post
                    Powered by NodeBB | Contributors