設(shè)備
筆者有一個(gè)需求,需要結(jié)合ROS做模擬量采集。有一種解決方法是ADC芯片+STM32主控,通過(guò)串口的方式與上位機(jī)通信,但串口通信速度很慢,達(dá)不到要求遂放棄。也考慮過(guò)使用NI的數(shù)據(jù)采集卡,貌似NI沒有給ubuntu作配套,也放棄了。在淘寶上找到一款凌智電子的DAQ,價(jià)格便宜,也能滿足使用需求,故做記錄。
系統(tǒng)環(huán)境 ubuntu20.04 + ROS noetic
硬件設(shè)備 i5-12500+凌智電子DAQ122
驅(qū)動(dòng)下載
驅(qū)動(dòng)要到gitee下載,支持ubuntu x86_64的驅(qū)動(dòng)要注意分支TestZKFT。
git clone --branch=TestZKFT https://gitee.com/Lockzhiner-Electronics/DAQ122-IPC.git
下在之后可以嘗試運(yùn)行 幾個(gè)demo,都是用Qt寫的,也可以拷貝Linux/libdaq的目錄單獨(dú)開發(fā)。最關(guān)鍵的是 liblibdaq-2.0.0.so這個(gè)文件,下面以ROS為例子怎么調(diào)用.so文件。
結(jié)合cmake的使用
新建工作空間,功能包等流程不再贅述,網(wǎng)上已經(jīng)有很多教程了。著重講cmakelist的配置。
沿用官方demo中QT的使用,因此
find_package(
Qt5 REQUIRED COMPONENTS Core Widgets
)
除此之外,還要包含頭文件目錄,除了包含官方libdaq的路徑以外,還要包含QT安裝的路徑
include_directories(
include/daq_122 #自己寫了一個(gè).h文件
${catkin_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/include/daq_122
${CMAKE_CURRENT_SOURCE_DIR}/include/daq_122/include
${CMAKE_CURRENT_SOURCE_DIR}/include/daq_122/third_party/include
${catkin_INCLUDE_DIRS}
${Qt5Core_INCLUDE_DIRS}
${Qt5Widgets_INCLUDE_DIRS}
)
鏈接官方的.so庫(kù)文件
link_directories(
lib/x86_64 # 相對(duì)路徑,指定動(dòng)態(tài)鏈接庫(kù)的訪問(wèn)路徑
${catkin_LIB_DIRS}
)
再就是ROS 編譯C++的cmake寫法了。雖然so文件叫l(wèi)iblibdaq-2.0.0,但cmake中需要去掉一個(gè)lib才能執(zhí)行下去。
add_library(${PROJECT_NAME}
src/daq_read.cpp
)
add_executable(daq_read src/daq_read.cpp)
add_dependencies(daq_read ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(daq_read
${catkin_LIBRARIES}
libdaq-2.0.0 #這里額外注意,編譯時(shí)候cmake會(huì)自動(dòng)加個(gè)前綴lib
Qt5::Core
Qt5::Widgets
)
至此,完成了cmakelist的寫法。
此外還有package.xml文件,需要引用如下
catkin
roscpp
rospy
std_msgs
qtbase5-dev
geometry_msgs
roscpp
rospy
std_msgs
geometry_msgs
roscpp
rospy
std_msgs
qtbase5-dev
geometry_msgs
其中g(shù)eometry_msgs是筆者實(shí)現(xiàn)自己功能用的一個(gè)包,可以不用,其他的包都是必須的。
ROS的寫法
現(xiàn)在要寫一個(gè).h文件,定義一些變量。之前cmake已經(jīng)有了對(duì)QT的引用,因此直接用QT函數(shù)就行。
# ifndef DAQ_READ_H
# define DAQ_READ_H
#include
#include
#include
#include
#include
using namespace libdaq::device;
DAQ122 daq_device;
uint8_t adc_channel_state_ = 0b11111111;
uint8_t legal_channel_size = 8;
uint32_t storage_depth = 1;
QVector> receive_data(8);
geometry_msgs::Vector3 laser_distance;
# endif
各個(gè)變量的作用,參考官方的示例即可。
接下來(lái)是C++文件,運(yùn)行程序要求有sudo 權(quán)限。筆者這里用前三個(gè)姿態(tài),以5K頻率讀,再以5K頻率發(fā)送,設(shè)置如下
#include
#include
#include "data_read.h"
/*
運(yùn)行這個(gè)程序要求sudo權(quán)限
sudo su
然后輸入你的用戶名+密碼
包含兩部分 ros+daq讀取
*/
void DAQcallback()
{
auto read_result = true;
for (int i = 0; i < 3; i++) {
// 判斷當(dāng)前通道是否打開,沒有打開則跳過(guò)
if((adc_channel_state_ & (0b00000001) << i) == 0){
continue;
}
// 讀取數(shù)據(jù)
read_result = daq_device.TryReadADCData(i, receive_data[i].data(), receive_data[i].size(), 1000);
if(!read_result){
}
}
QVector x_data(storage_depth);
for (int var = 0; var < storage_depth; ++var) {
x_data[var] = 1000.0 / storage_depth * var;
}
// read_result = daq_device.TryReadADCData(1,receive_data.data(),10,10);
// 只配置了三個(gè)通道
auto current_buffer_size = daq_device.GetADCBufferDataSize(0);
qDebug() << receive_data[1];
// 停止讀取
// daq_device.StopADCCollection();
// receive_data[0].clear();
// receive_data[1].clear();
// receive_data[2].clear();
laser_distance.x = receive_data[0].at(0);
laser_distance.y = receive_data[1].at(0);
laser_distance.z = receive_data[2].at(0);
}
int main(int argc, char *argv[])
{
// 初始化DAQ122
if (!daq_device.InitializeDevice())
{
std::cout << "InitializeDevice Error";
}
if(!daq_device.ConnectedDevice())
{
std::cout << "ConnectedDevice Error";
}
// 采樣范圍5V
auto voltage_range = DAQVoltage::Voltage5V;
// 采樣頻率定義為1KHz
auto sample_rate = DAQADCSampleRate::SampleRate5K;
if (!daq_device.ConfigureADCParameters(sample_rate, voltage_range))
{
std::cout << "Configure Error";
}
// 配置前三個(gè)通道為輸入
adc_channel_state_ = DAQADCChannel::AIN1 | DAQADCChannel::AIN2 | DAQADCChannel::AIN3;
daq_device.ConfigADCChannel(adc_channel_state_);
// 開始采集數(shù)據(jù)
daq_device.StartADCCollection();
// 定義存儲(chǔ)數(shù)組
for (int var = 0; var < receive_data.size(); ++var) {
receive_data[var].resize(storage_depth);
}
// ros初始化
ros::init(argc,argv,"daq_pub_node");
ros::NodeHandle nh;
// 1ms 執(zhí)行一次
ros::Publisher daq_pub = nh.advertise("daq_pub",10);
ros::Duration(1).sleep();
// 判斷當(dāng)前數(shù)據(jù)是否已經(jīng)滿足讀取的條件
if(!daq_device.ADCDataIsReady(storage_depth)){
std::cout << "not enough" << std::endl;
}
auto read_result = true;
for (int i = 0; i < legal_channel_size; i++) {
// 判斷當(dāng)前通道是否打開,沒有打開則跳過(guò)
if((adc_channel_state_ & (0b00000001) << i) == 0){
continue;
}
// 讀取數(shù)據(jù)
read_result = daq_device.TryReadADCData(i, receive_data[i].data(), receive_data[i].size(), 1000);
if(!read_result){
// qDebug() << "Error";
}
}
QVector x_data(storage_depth);
for (int var = 0; var < storage_depth; ++var) {
x_data[var] = 1000.0 / storage_depth * var;
}
ros::Rate daq_rate(5000);
while (ros::ok())
{
DAQcallback();
daq_pub.publish(laser_distance);
daq_rate.sleep();
}
// ros::spin();
return 0;
}
編譯,運(yùn)行即可將數(shù)據(jù)發(fā)送到rostopic中。
采集正弦信號(hào)
采集方波信號(hào)
采集三角波信號(hào)
-
串口通信
+關(guān)注
關(guān)注
34文章
1626瀏覽量
55528 -
ROS
+關(guān)注
關(guān)注
1文章
278瀏覽量
17009 -
模擬量采集
+關(guān)注
關(guān)注
0文章
23瀏覽量
2952
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論