实习记录(三):学习测试雷达同步板 & 完成外部硬件触发装置

学习测试雷达同步板 & 完成外部硬件触发装置

2020.07.27~2020.07.31、2020.08.03

1.任务

1)学习现有雷达同步板,测试现有雷达同步板精度
2)STM32实现用串口接收四位数,接收到瞬间一发出高电平,并且根据数字大小设置高电平持续时间
3)使用boost::asio库在ubuntu系统上写一个周期性向串口发送信息的类

2.环境 & 工具

STM32F103RCT6
串口USB转接线
上面两个东西要看原理图,硬件连接和代码管脚选择需要它们

1) 同步板
STM32F103RCT6 和 扩展板
示波器RIGOL-DS2072A

2)windows
STM32CubeMX
Keil5
XCOM
FlyMCU

3)ubuntu16.04
ROS kinetic
cutecom

3.准备工作

3.1 同步板部分

读已有代码,了解大致功能
提供的说明与测试不符,所以先用万用表将每个管脚的定义分清楚

3.2 STM32部分

STM32CubeMX新建项目,进行配置:

  • 一个输出管脚
  • 一组串口USART
  • 时钟相关配置

生成代码,用keil5打开项目

3.3 ubuntu部分

创建工作空间,创建包
vscode配置
以上实习记录(一)中有记录

4.代码

4.1 同步板部分

4.2 STM32部分
//第一处代码
/* USER CODE BEGIN 2 */
 //测试提示用
  //HAL_UART_Transmit(&huart1, (uint8_t *)"初始化成功", 12, 0xFFFF);
/* USER CODE END 2 */

//第二处代码
/* USER CODE END WHILE */
    char rx_message[RXSIZE] = {0};
    uint16_t rx_int = 0;

    /* USER CODE END 2 */

    HAL_UART_Receive(&huart1, (uint8_t *)&rx_message, RXSIZE, 0xffff);
    //HAL_UART_Transmit(&huart1, (uint8_t *)&rx_message, RXSIZE, 0xffff);
    while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);

    for (int i = 0; i < RXSIZE; i++) {
      rx_int = rx_int + ((int)rx_message[i] - 48) * pow(10, RXSIZE - i - 1);
    }
    
    //HAL_UART_Transmit(&huart1, (uint8_t *)&rx_int, RXSIZE, 0xffff);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
    HAL_Delay(rx_int);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);

    /* USER CODE BEGIN 3 */

4.3 ubuntu部分
//main.cpp
#include "writer_handler.h"
#include <boost/thread/thread.hpp>

int main(int argc, char* argv[])
{
  std::cout << "Program Start ..." << std::endl;

  while (1)
  {
    try
    {
      xxxx::SerialPortWriter my_sp("/dev/ttyUSB0", "0300");
      // my_sp.serialRead();
      my_sp.handleCall();
    }
    catch (std::exception& err)
    {
      std::cout << err.what() << std::endl;
    }
    boost::this_thread::sleep(boost::posix_time::milliseconds(500));
  }

  return 0;
}

//.h
#ifndef WRITER_HANDLER_H
#define WRITER_HANDLER_H

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

typedef std::string any_type;

namespace xxxx
{
class SerialPortWriter
{
public:
  SerialPortWriter(const any_type& port_name, const any_type data);

  ~SerialPortWriter();

  void serialWrite(const any_type data);

  void serialRead();

  void handleCall();

private:
  boost::asio::io_service my_ios_;

  boost::asio::serial_port* p_serial_port_;

  boost::system::error_code ec_;
};
}  // namespace xxxx

#endif

//.cpp
#include "writer_handler.h"

#define MSGSIZE 4

namespace xxxx
{
SerialPortWriter::SerialPortWriter(const any_type& port_name, const any_type data) : p_serial_port_(NULL)
{
  p_serial_port_ = new boost::asio::serial_port(my_ios_);
  p_serial_port_->open(port_name, ec_);
  p_serial_port_->set_option(boost::asio::serial_port::baud_rate(115200), ec_);
  p_serial_port_->set_option(boost::asio::serial_port::flow_control(boost::asio::serial_port::flow_control::none), ec_);
  p_serial_port_->set_option(boost::asio::serial_port::parity(boost::asio::serial_port::parity::none), ec_);
  p_serial_port_->set_option(boost::asio::serial_port::stop_bits(boost::asio::serial_port::stop_bits::one), ec_);
  p_serial_port_->set_option(boost::asio::serial_port::character_size(8), ec_);

  serialWrite(data);
}

SerialPortWriter::~SerialPortWriter()
{
  if (p_serial_port_)
  {
    delete p_serial_port_;
  }
}

void SerialPortWriter::serialWrite(const any_type data)
{
  p_serial_port_->write_some(boost::asio::buffer(data), ec_);
  std::cout << "\nwrite: " << data << std::endl;
}

void SerialPortWriter::serialRead()
{
  char v[MSGSIZE];
  p_serial_port_->read_some(boost::asio::buffer(v, MSGSIZE), ec_);
  std::cout << "\nread: " << v << std::endl;
}

void SerialPortWriter::handleCall()
{
  my_ios_.run();
}

}  // namespace xxxx

//cmakelist
//直接用自动生成的提示文档修改的,其中前面有#的都是无效部分
cmake_minimum_required(VERSION 3.0.2)
project(serial_writer)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
)

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES serial_writer
#  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
 include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
add_library(writer_handler
   src/writer_handler.cpp
   include/writer_handler.h
)

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_dependencies(
  writer_handler 
  ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(
  serial_writer_main 
  src/serial_writer_main.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")




## Specify libraries to link a library or executable target against
target_link_libraries(
  serial_writer_main
  writer_handler
  ${catkin_LIBRARIES}
)

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# catkin_install_python(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_serial_writer.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

5.运行测试

5.1 同步板部分
周期个数 start end 平均周期 平均误差
第一组 50 -42.87s 7.123s 999.86111ms -0.13889ms
第二组 50 -47.88s 2.110s 999.84615ms -0.15385ms
第三组 50 -38.07s 11.92s 999.80000ms -0.20000ms
第四组 50 -49.87s 124.1ms 999.88200ms -0.11800ms
第五组 50 -41.09s 8.898s 999.76000ms -0.24000ms

以上五组平均误差为:-0.170418ms

  • 发现该示波器确实存在精度误差,难以测得需要精度的正确值
  • 故找硬件组帮忙测试,超大示波器,据说三十万一台,能连鼠标键盘,还能触屏
  • 发现之前测试成了 TTL-DATA 端口,应该测试的是 TTL-PPS 端口,两者的最大波形周期是相同的,但TTL-DATA端口的每个大波形上又许多大小不等的小方波,是时间戳信息
  • 并且还发现,GPS接上后,同步板的PPS输出会在一定时间时突然出现一个下降沿,可能是单片机时钟自动归位造成的现象
5.2 STM32部分

用串口USB转接线连接STM32和电脑

用FlyMcu用hex文件将项目编译进STM32

用XCOM向串口发送信息,看返回信息是否正确,并且用示波器检查输出管脚的波形

5.3 ubuntu部分

用命令给USB开启权限(在这里卡了好久,一直以为代码有问题,一定要检查硬件啊,哭~

#查看连接的USB转串口
ls -l /dev/ttyUSB*
#usb给权限
sudo chmod 777 /dev/ttyUSB0

用串口USB转接线插入电脑,自己的RX和TX接上

编译运行串口发送程序,观察返回值是否正确

或者两根转接线把两台电脑连接起来,另一台用cutecom观察返回值

5.3  综合测试

用串口USB转接线连接STM32和电脑

编译运行串口发送程序,修改数值多测几组

用示波器检测输出管脚波形


结语:开始工作之前一定要把需求确定清楚,方案交流清楚,花了大半天研究怎么用串口中断接收不定长信息,前辈过来看直接表示,外部触发实际使用中信息一定是定长定类型的,这么做没有必要。好吧,又绕路了,方向确实非常重要,不然容易白做功。硬件和软件一样需要检查,运行有问题两者的原因都有可能。之前还是孤陋寡闻了,boost库第一次使用,临时学习也花了一些时间。

注:本文为自用实习记录

猜你喜欢

转载自blog.csdn.net/o66oCZRo99o/article/details/107753381