00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <iostream>
00039 #include <string>
00040 #include <ros/ros.h>
00041 #include "smi540/smi540.h"
00042 #include <sstream>
00043 #include <ros/time.h>
00044 #include <math.h>
00045 #include <vector>
00046
00047 Smi540::Smi540(std::string sSub20Serial):
00048 bSubDeviceOpen (false),
00049 bSubDeviceConfigured (false),
00050 strSerial (" ")
00051 {
00052 int spi_error_code;
00053 int iSPI_cfg_set;
00054 int iSPI_cfg_get;
00055 sub_device sub20dev;
00056 sub_handle sub20handle;
00057 std::cout << "---opening SUB device---" << " \n";
00058 std::string sub20serial;
00059 OneSub20Config OneSub20Configuration;
00060
00062
00064 sub20dev = 0;
00065 sub20dev = sub_find_devices(sub20dev);
00066 std::cout << "sub 20 Device: " << sub20dev << std::endl;
00067 while( sub20dev != 0 )
00068 {
00069 sub20handle = sub_open(sub20dev);
00070
00071 if( sub20handle == 0 )
00072 {
00073
00074 ROS_INFO("ERROR - Sub20 could not be opened: %s ", sub_strerror(sub_errno) );
00075 }
00076 else
00077 {
00078
00079 sub20serial.clear();
00080 sub20serial.resize( smi540_cmd::uSERIALNUMLENGTH );
00081 sub_get_serial_number(sub20handle, const_cast<char*>(sub20serial.c_str()), sub20serial.size());
00082 std::cout << "Serial Number : " << sub20serial << std::endl;
00083
00084 if( strcmp(sub20serial.c_str(), sSub20Serial.c_str()) == 0 )
00085 {
00087
00089 subhndl = sub20handle;
00090 bSubDeviceOpen = true;
00091 std::cout << "---Initializing SPI Interface---" << std::endl;
00092
00093 spi_error_code = sub_spi_config( sub20handle, 0, &iSPI_cfg_get );
00094 std::cout << "Dev Sub config : " << iSPI_cfg_get << " \n";
00095
00096 iSPI_cfg_set = SPI_ENABLE|SPI_CPOL_RISE|SPI_SMPL_SETUP|SPI_MSB_FIRST|SPI_CLK_1MHZ;
00097
00098 spi_error_code = sub_spi_config( sub20handle, iSPI_cfg_set, 0 );
00099
00100 spi_error_code = sub_spi_config( sub20handle, 0, &iSPI_cfg_get );
00101
00102
00103 if( iSPI_cfg_get == iSPI_cfg_set )
00104 {
00105 bSubDeviceConfigured = true;
00106 std::cout<< "Configuration : " << iSPI_cfg_set << " successfully stored \n";
00107
00108 OneSub20Configuration.bSubSPIConfigured = true;
00109 OneSub20Configuration.handle_subdev = sub20handle;
00111
00113 std::cout<< "Configuring SMI540 device" << std::endl;
00114 confsens_on_sub20( &OneSub20Configuration);
00115 }
00116 else
00117 {
00118 std::cout<< "ERROR - Configuration :" << iSPI_cfg_set << " not accept by device \n";
00119
00120 bSubDeviceConfigured = false;
00121 OneSub20Configuration.bSubSPIConfigured = false;
00122 }
00123
00124
00125 if( OneSub20Configuration.bSubSPIConfigured )
00126 {
00127
00128
00129
00130 spi_error_code = sub_spi_transfer( sub20handle, smi540_cmd::chTRIGGER_RESET, 0, 4, SS_CONF(0,SS_LO) );
00131 strSerial.clear();
00132 strSerial.resize( smi540_cmd::uSERIALNUMLENGTH );
00133 sub_get_serial_number( sub20handle, const_cast<char*>(strSerial.c_str()), strSerial.size() );
00134 OneSub20Configuration.strSub20Serial = strSerial;
00135 OneSub20Configuration.subdev = sub20dev;
00136 std::cout << "Device Handle : " << OneSub20Configuration.handle_subdev << std::endl;
00137 std::cout << "Serial Number : " << OneSub20Configuration.strSub20Serial << std::endl;
00139
00141 Sub20Device_list.push_back (OneSub20Configuration);
00142 std::cout << "... Publishing to topic /smi540 ... " << std::endl;
00143 }
00144 break;
00145 }
00146 else
00147 {
00148 sub_close( sub20handle );
00149 }
00150 }
00151
00152 sub20dev = sub_find_devices( sub20dev );
00153 }
00154 };
00155
00156 Smi540::~Smi540()
00157 {
00158 int spi_error_code;
00159 OneSub20Config OneSub20Configuration;
00160
00161 spi_error_code = sub_spi_config( subhndl, 0, 0 );
00162
00163 sub_close( subhndl );
00164
00165 bSubDeviceOpen = false;
00166 bSubDeviceConfigured = false;
00167 while( !Sub20Device_list.empty() )
00168 {
00169 OneSub20Configuration = Sub20Device_list.back();
00170 std::cout << "Sub device removed " << OneSub20Configuration.strSub20Serial << "\n";
00171 Sub20Device_list.pop_back();
00172 }
00173 };
00174
00175
00176 void Smi540::GetMeasurements( std::list<OneSmi540Meas> &list_meas )
00177 {
00178 char chMM5_rx[8], chCMD;
00179 int spi_error_code, iChipSelect, j = 0;
00180 OneSmi540Meas sMeas;
00181 unsigned short smi540health;
00182 double dAccX, dAccY, dRateZ;
00183 bool SPIMeas = false;
00184 std::list<OneSub20Config>::iterator iterat;
00185
00186
00187 if( 1 > (int)Sub20Device_list.size() )
00188 {
00189 throw std::string ("No SubDevice connected OR access rights to USB not given");
00190 }
00191
00192 for( iterat = Sub20Device_list.begin(); iterat != Sub20Device_list.end(); iterat++ )
00193 {
00194
00195 if( iterat->bSubSPIConfigured == true )
00196 {
00197
00198 for( iChipSelect = 0; iChipSelect < smi540_cmd::MAX_SENSORS; iChipSelect++ )
00199 {
00200
00201 if( iterat->Smi540Cluster[iChipSelect].bConfigured == true )
00202 {
00203 spi_error_code = 0;
00204
00205
00206 spi_error_code += sub_spi_transfer( iterat->handle_subdev, smi540_cmd::chRD_ACT_DATA_64, 0, 4, SS_CONF(iChipSelect,SS_LO) );
00207 if( spi_error_code != 0 )
00208 {
00209 ROS_WARN("SPI transfer result: %d\tCS: %d, ", spi_error_code, iChipSelect);
00210 }
00211 spi_error_code += sub_spi_transfer( iterat->handle_subdev, 0, chMM5_rx, 8, SS_CONF(iChipSelect,SS_LO) );
00212
00213
00214 if( spi_error_code == 0 )
00215 {
00216 SPIMeas = true;
00217
00218 dRateZ = mm5data_to_double(chMM5_rx[5], chMM5_rx[6], smi540_cmd::eGYRO);
00219 dAccX = mm5data_to_double(chMM5_rx[3], chMM5_rx[4], smi540_cmd::eACCEL);
00220 dAccY = mm5data_to_double(chMM5_rx[1], chMM5_rx[2], smi540_cmd::eACCEL);
00221
00222
00223 sMeas.dAccX[j] = dAccX;
00224 sMeas.dAccY[j] = dAccY;
00225 sMeas.dRateZ[j] = dRateZ;
00226 sMeas.iChipSelect[j] = iChipSelect;
00227 j++;
00228 sMeas.iNumAccels = j;
00229
00230 smi540health = (unsigned short)( chMM5_rx[0] & 0x23 );
00231 }
00232 else
00233 {
00234 throw std::string ("SPI transfer error");
00235 }
00236 }
00237 }
00238 }
00239
00240 if( SPIMeas )
00241 {
00242 sMeas.dtomeas = ros::Time::now();
00243 sMeas.bMeasAvailable = true;
00244 sMeas.strSerial = iterat->strSub20Serial;
00245
00246 list_meas.push_back( sMeas );
00247 }
00248 else
00249 {
00250 throw std::string ("SUB20 connected but no access rights given!");
00251 }
00252 }
00253 }
00254
00255 double Smi540::mm5data_to_double( char chMSB, char chLSB, smi540_cmd::eSensorType eSensor )
00256 {
00257 short s16int;
00258 double dSensorMeas;
00259
00260 if( (chMSB & 0x80) == 0 )
00261 {
00262
00263 s16int = (short) ((((unsigned short)chMSB)&0xFF)<<8) + (((unsigned short)chLSB)&0xFF);
00264 }
00265 else {
00266
00267
00268 s16int = (short)(((((unsigned short)chMSB)&0x7F)<<8) + (((unsigned short)chLSB)&0xFF)-32768);
00269 }
00270
00271
00272 if( eSensor == smi540_cmd::eACCEL )
00273 {
00274 dSensorMeas = ((double)s16int) / smi540_cmd::fSFACC_inv;
00275 }
00276 else
00277 {
00278 dSensorMeas = ((double)s16int) / smi540_cmd::fSFGYRO_inv;
00279 }
00280 return (dSensorMeas);
00281 }
00282
00283 void Smi540::confsens_on_sub20( OneSub20Config *pOneSub20Conf )
00284 {
00285 int spi_error_code;
00286 int iChipSelect;
00287 sub_handle handle_sub20;
00288 char chCMD[8];
00289
00290
00291 handle_sub20 = pOneSub20Conf->handle_subdev;
00292 for( iChipSelect = 0; iChipSelect < smi540_cmd::MAX_SENSORS; iChipSelect++ )
00293 {
00294 spi_error_code = 0;
00295
00296 spi_error_code += sub_spi_transfer( handle_sub20, 0, &chCMD[0], 1, SS_CONF(iChipSelect,SS_H) );
00297
00298
00299
00300 spi_error_code += sub_spi_transfer( handle_sub20, smi540_cmd::chTRIGGER_RESET, 0, 4, SS_CONF(iChipSelect,SS_LO) );
00301 spi_error_code += sub_spi_transfer( handle_sub20, 0, &chCMD[0], 1, SS_CONF(iChipSelect,SS_H) );
00302 spi_error_code += sub_spi_transfer( handle_sub20, smi540_cmd::chRD_STATUS_A, 0, 4, SS_CONF(iChipSelect,SS_LO) );
00303 spi_error_code += sub_spi_transfer( handle_sub20, 0, chCMD, 8, SS_CONF(iChipSelect,SS_LO) );
00304
00305
00306 if( (spi_error_code == 0) && (strlen(chCMD)<=1) )
00307 {
00308 ROS_INFO("-----------------------------------------");
00309 ROS_INFO("SMI 540 - Chip Select %d", iChipSelect);
00310 ROS_INFO("CONFIGURED");
00311 pOneSub20Conf->Smi540Cluster[iChipSelect].bConfigured = true;
00312 } else {
00313 ROS_INFO("-----------------------------------------");
00314 ROS_INFO("SMI 540 - Chip Select %d", iChipSelect);
00315 ROS_INFO("NO SENSOR DETECTED");
00316 pOneSub20Conf->Smi540Cluster[iChipSelect].bConfigured = false;
00317 }
00318
00319 }
00320 };
00321
00322
00323
00324
00325 int main( int argc, char **argv )
00326 {
00327 double dRate_Hz;
00328 std::string sSub20Serial;
00329 ros::init(argc, argv, "smi540");
00330 ros::NodeHandle nh;
00331 ros::Publisher smi540_pub = nh.advertise<smi540::smi540meas>("smi540", 100);
00332
00333 if( nh.getParam("/smi540/rate_Hz", dRate_Hz ) == false )
00334 {
00335 dRate_Hz = smi540_cmd::DEFAULT_RATE_Hz;
00336 };
00337 if(nh.getParam("/smi540/sub20serial", sSub20Serial) == false )
00338 {
00339 sSub20Serial = smi540_cmd::sSUB20SERIAL;
00340 };
00341
00342 Smi540 smi540_attached(sSub20Serial);
00343 OneSmi540Meas sOneMeas;
00344 smi540::smi540meas msg;
00345 std::list<OneSmi540Meas>measurements_list;
00346
00347 ros::Rate loop_rate(dRate_Hz);
00348
00349 while( nh.ok() )
00350 {
00351
00352 try
00353 {
00354 smi540_attached.GetMeasurements( measurements_list );
00355 }
00356 catch ( std::string strType )
00357 {
00358 ROS_WARN_STREAM("An exception occurred: " << strType);
00359
00360 continue;
00361 }
00362
00363 while( !measurements_list.empty() )
00364 {
00365 sOneMeas = measurements_list.back();
00366 measurements_list.pop_back();
00367
00368 if( sOneMeas.bMeasAvailable == true )
00369 {
00370 msg.strIdSubDev = sOneMeas.strSerial;
00371
00372
00373 for( int i = 0; i < sOneMeas.iNumAccels; i++ )
00374 {
00375 msg.iChipSelect.push_back( sOneMeas.iChipSelect[i] );
00376 msg.fAcclX.push_back( sOneMeas.dAccX[i] );
00377 msg.fAcclY.push_back( sOneMeas.dAccY[i] );
00378 msg.fRateZ.push_back( sOneMeas.dRateZ[i] );
00379 }
00380 msg.header.stamp = sOneMeas.dtomeas;
00381 smi540_pub.publish( msg );
00382
00383
00384 msg.iChipSelect.clear();
00385 msg.fAcclX.clear();
00386 msg.fAcclY.clear();
00387 msg.fRateZ.clear();
00388 }
00389 }
00390 ros::spinOnce();
00391 loop_rate.sleep();
00392 }
00393 }
00394