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 #include <iostream>
00037 #include <string>
00038 #include "ros/ros.h"
00039 #include <sstream>
00040 #include "ros/time.h"
00041 #include <math.h>
00042 #include "adc_sub20/sub20_ADC.h"
00043 #include <vector>
00044 #include <map>
00045
00046 Sub20_ADC::Sub20_ADC(std::string ADC_MUXCONFIG, double dRate_Hz, double dVRef):
00047 bSubDeviceOpen (false),
00048 bSubDeviceConfigured (false)
00049 {
00050
00051 int iADCErr;
00052 int iADC_cfg_set;
00053 std::stringstream ss_errmsg;
00054 std::string ss_config;
00055 sub_device sub20dev;
00056 sub_handle sub20handle;
00057 OneSub20Config OneSub20Configuration;
00058
00059 ROS_INFO("--------------------------------------");
00060 initADC_MUX_MAP();
00062
00064 sub20dev = 0;
00065 sub20dev = sub_find_devices(sub20dev);
00066 while( sub20dev != 0 ) {
00067 sub20handle = sub_open( sub20dev );
00068
00069 if (sub20handle > 0) {
00070 subhndl = sub20handle;
00072
00074 std::cout << "---Initializing ADC Interface---" << std::endl;
00075
00076 iADC_cfg_set = ADC_ENABLE;
00077 ss_config = "ADC_ENABLE | ";
00078 if((dVRef==VCC_5V)||(dVRef==VCC_3V3)){
00079 iADC_cfg_set |= ADC_REF_VCC;
00080 ss_config += "ADC_REF_VCC";
00081 } else {
00082 iADC_cfg_set |= ADC_REF_2_56;
00083 ss_config += "ADC_REF_2_56";
00084 }
00085
00086 iADCErr = sub_adc_config( sub20handle, iADC_cfg_set);
00087 if(iADCErr == 0) {
00088 std::cout << "ADC Configuration : " << iADC_cfg_set << " successfully stored \n";
00089 std::cout << "Configuration Details : " << std::endl;
00090 std::cout << " Register Settings : " << ss_config << std::endl;
00091 std::cout << " ADC Readings Rate (/sec) : " << dRate_Hz << std::endl;
00092
00093
00094 get_ADC_MuxCode(ADC_MUXCONFIG, OneSub20Configuration.sub20_ADC_Config.sub20_ADC_MUX, OneSub20Configuration.sub20_ADC_Config.sub20_ADC_TYPE, &OneSub20Configuration.sub20_ADC_Config.Num_Chans);
00095 std::cout << " ADC Channels Selected : " << ADC_MUXCONFIG << std::endl;
00096 OneSub20Configuration.bSubDevConfigured = true;
00097
00098
00099 strSerial.clear();
00100 strSerial.resize(sub20_ADC_cmd::uSERIALNUMLENGTH);
00101 sub_get_serial_number(sub20handle, const_cast<char*>(strSerial.c_str()), strSerial.size());
00102 OneSub20Configuration.strSub20Serial = strSerial;
00103 OneSub20Configuration.handle_subdev = sub20handle;
00104 OneSub20Configuration.subdev = sub20dev;
00105 std::cout << "Device Handle : " << OneSub20Configuration.handle_subdev << std::endl;
00106 std::cout << "Serial Number : " << OneSub20Configuration.strSub20Serial << std::endl;
00107
00109
00111 Sub20Device_list.push_back (OneSub20Configuration);
00112 std::cout << "Serial : " << OneSub20Configuration.strSub20Serial << "\n";
00113 } else {
00114 ROS_INFO("ERROR - Configuration : %d not accepted by device", iADC_cfg_set);
00115
00116 OneSub20Configuration.bSubDevConfigured = false;
00117 }
00118 }
00119
00120 sub20dev = sub_find_devices(sub20dev);
00121 }
00122 ROS_INFO("--------------------------------------");
00123 std::cout << " ************* Publishing to rostopic - /sub20_ADC ************* " << std::endl;
00124 }
00125
00126 Sub20_ADC::~Sub20_ADC() {
00127
00128 int iSpiErr;
00129 OneSub20Config OneSub20Configuration;
00130
00131
00132 iSpiErr = sub_spi_config( subhndl, 0, 0 );
00133
00134 sub_close( subhndl );
00135 while (!Sub20Device_list.empty()) {
00136 OneSub20Configuration = Sub20Device_list.back ();
00137 std::cout << "Sub device removed " << OneSub20Configuration.strSub20Serial << "\n";
00138 Sub20Device_list.pop_back ();
00139 }
00140 }
00141
00142
00143 void Sub20_ADC::initADC_MUX_MAP(){
00144 sub20_ADC_cmd::adcMuxMap["ADC_S0"] = ADC_S0;
00145 sub20_ADC_cmd::adcMuxMap["ADC_S1"] = ADC_S1;
00146 sub20_ADC_cmd::adcMuxMap["ADC_S2"] = ADC_S2;
00147 sub20_ADC_cmd::adcMuxMap["ADC_S3"] = ADC_S3;
00148 sub20_ADC_cmd::adcMuxMap["ADC_S4"] = ADC_S4;
00149 sub20_ADC_cmd::adcMuxMap["ADC_S5"] = ADC_S5;
00150 sub20_ADC_cmd::adcMuxMap["ADC_S6"] = ADC_S6;
00151 sub20_ADC_cmd::adcMuxMap["ADC_S7"] = ADC_S7;
00152
00153 sub20_ADC_cmd::adcMuxMap["ADC_D10_10X"] = ADC_D10_10X;
00154 sub20_ADC_cmd::adcMuxMap["ADC_D10_200X"] = ADC_D10_200X;
00155 sub20_ADC_cmd::adcMuxMap["ADC_D32_10X"] = ADC_D32_10X;
00156 sub20_ADC_cmd::adcMuxMap["ADC_D32_200X"] = ADC_D32_200X;
00157
00158 sub20_ADC_cmd::adcMuxMap["ADC_D01"] = ADC_D01;
00159 sub20_ADC_cmd::adcMuxMap["ADC_D21"] = ADC_D21;
00160 sub20_ADC_cmd::adcMuxMap["ADC_D31"] = ADC_D31;
00161 sub20_ADC_cmd::adcMuxMap["ADC_D41"] = ADC_D41;
00162 sub20_ADC_cmd::adcMuxMap["ADC_D51"] = ADC_D51;
00163 sub20_ADC_cmd::adcMuxMap["ADC_D61"] = ADC_D61;
00164 sub20_ADC_cmd::adcMuxMap["ADC_D71"] = ADC_D71;
00165 sub20_ADC_cmd::adcMuxMap["ADC_D02"] = ADC_D02;
00166 sub20_ADC_cmd::adcMuxMap["ADC_D12"] = ADC_D12;
00167 sub20_ADC_cmd::adcMuxMap["ADC_D32"] = ADC_D32;
00168 sub20_ADC_cmd::adcMuxMap["ADC_D42"] = ADC_D42;
00169 sub20_ADC_cmd::adcMuxMap["ADC_D52"] = ADC_D52;
00170
00171 sub20_ADC_cmd::adcMuxMap["ADC_1_1V"] = ADC_1_1V;
00172 sub20_ADC_cmd::adcMuxMap["ADC_GND"] = ADC_GND;
00173 }
00174
00175
00176 void Sub20_ADC::get_ADC_MuxCode(std::string ADC_MUXCONFIG, int *adc_mux, int *adc_type, int *channels) {
00177
00178 unsigned int i=0, j=0, numVal=0;
00179 size_t charLocn[sub20_ADC_cmd::iMAXNUM_OF_CHANNELS], found;
00180 std::string ADCMux_Cfg[sub20_ADC_cmd::iMAXNUM_OF_CHANNELS], tmpStr;
00181
00182 size_t strlen = ADC_MUXCONFIG.length();
00183
00184 charLocn[0] = ADC_MUXCONFIG.find("|");
00185 if(charLocn[0] != std::string::npos){
00186 ADCMux_Cfg[0] = ADC_MUXCONFIG.substr(0,charLocn[0]);
00187 adc_mux[j] = sub20_ADC_cmd::adcMuxMap[ADCMux_Cfg[0]];
00188
00189 tmpStr = ADCMux_Cfg[0];
00190 found = tmpStr.find("S");
00191 if(found != std::string::npos) {
00192 adc_type[j] = 0;
00193 } else {
00194 found = tmpStr.find("D");
00195 if(found != std::string::npos){
00196 adc_type[j] = 1;
00197 } else {
00198 adc_type[j] = 2;
00199 }
00200 }
00201 j++; numVal++;
00202 }
00203 for(i=1; i<strlen; i++){
00204 charLocn[i] = ADC_MUXCONFIG.find("|",(charLocn[i-1]+1));
00205 if(charLocn[i] == std::string::npos){
00206 break;
00207 }
00208 ADCMux_Cfg[i] = ADC_MUXCONFIG.substr((charLocn[i-1]+1),((charLocn[i]-charLocn[i-1])-1));
00209 adc_mux[j] = sub20_ADC_cmd::adcMuxMap[ADCMux_Cfg[i]];
00210
00211 tmpStr = ADCMux_Cfg[i];
00212 found = tmpStr.find("S");
00213 if(found != std::string::npos) {
00214 adc_type[j] = 0;
00215 } else {
00216 found = tmpStr.find("D");
00217 if(found != std::string::npos){
00218 adc_type[j] = 1;
00219 } else {
00220 adc_type[j] = 2;
00221 }
00222 }
00223 j++; numVal++;
00224 }
00225 *channels = numVal;
00226 }
00227
00228 double Sub20_ADC::adc_To_Volts(int rawData, char convType, int muxCode, double dVRef){
00229 double value = 0, gain = 0;
00230
00231
00232 switch(convType){
00233 case 0:
00234 value = (rawData*dVRef)/1023;
00235 break;
00236 case 1:
00237 if((muxCode==ADC_D10_10X)||(muxCode==ADC_D32_10X)){
00238 gain = 10;
00239 } else if((muxCode==ADC_D10_200X)||(muxCode==ADC_D32_200X)){
00240 gain = 200;
00241 } else {
00242 gain = 1;
00243 }
00244 value = (rawData*dVRef)/(512*gain);
00245 break;
00246 case 2:
00247 value = rawData;
00248 break;
00249 default:
00250 break;
00251 }
00252 return value;
00253 }
00254
00255 void Sub20_ADC::GetMeasurements(std::list<OneSub20_ADC_Meas> &list_meas, double dVRef, int *channels) {
00256
00257 int iADCErr;
00258 OneSub20_ADC_Meas sMeas;
00259 ros::Time dtomeas;
00260 std::stringstream ss_errmsg;
00261 std::list<OneSub20Config>::iterator iterat;
00262 int sub20_ADC_BUF[16];
00263 int adc_buf, adc_mux;
00264 int Num_Chans;
00265
00266
00267 if (1 > (int)Sub20Device_list.size()) {
00268 throw std::string ("No SubDevice connected OR access rights to USB not given");
00269 }
00270
00271
00272
00273 for (iterat = Sub20Device_list.begin(); iterat != Sub20Device_list.end(); iterat++ ) {
00274
00275 if (iterat->bSubDevConfigured == true) {
00276 Num_Chans = iterat->sub20_ADC_Config.Num_Chans;
00277
00278
00279 sMeas.bMeasAvailable = true;
00280 for (int i=0; i<Num_Chans; i++){
00281 adc_mux = iterat->sub20_ADC_Config.sub20_ADC_MUX[i];
00282 iADCErr = sub_adc_single(iterat->handle_subdev, &adc_buf, adc_mux);
00283 sub20_ADC_BUF[i] = adc_buf;
00284 if(iADCErr == 0){
00285 sMeas.uiADCRaw[i] = sub20_ADC_BUF[i];
00286 sMeas.fADCVolt[i] = adc_To_Volts(sub20_ADC_BUF[i], iterat->sub20_ADC_Config.sub20_ADC_TYPE[i], iterat->sub20_ADC_Config.sub20_ADC_MUX[i], dVRef);
00287 } else {
00288 sMeas.bMeasAvailable = true;
00289 throw std::string ("Error on ADC conversion - Unplug or reset Sub20 Device");
00290 }
00291 }
00292 sMeas.dtomeas = ros::Time::now();
00293 sMeas.strSerial = iterat->strSub20Serial;
00294
00295 list_meas.push_back (sMeas);
00296
00297
00298
00299 } else {
00300 throw std::string ("SUB20 connected but not configured - Restart of node suggested");
00301 }
00302 }
00303 *channels = Num_Chans;
00304 }
00305
00306
00307
00308
00309 int main(int argc, char **argv) {
00310
00311
00312
00313
00314 int count = 1;
00315
00316 ros::init(argc, argv, "adc_sub20");
00317 ros::NodeHandle n;
00318 ros::Publisher sub20_ADC_pub = n.advertise<adc_sub20::sub20_ADC_meas>("adc_sub20", 100);
00319
00320 double dRate_Hz;
00321 double dVRef;
00322 int Num_Chans;
00323
00324 std::string ADC_MUXCONFIG;
00325
00326
00327
00328
00329
00330
00331 if (n.getParam("/adc_sub20/ADC_MUX_CONFIG", ADC_MUXCONFIG) == false ) {
00332 ADC_MUXCONFIG = sub20_ADC_cmd::sDEFAULT_ADC_MUXCONFIG;
00333 };
00334 if (n.getParam("/adc_sub20/rate_Hz", dRate_Hz) == false ) {
00335 dRate_Hz = sub20_ADC_cmd::dDEFAULT_RATE_Hz;
00336 };
00337 if (n.getParam("/adc_sub20/VoltRef", dVRef) == false ) {
00338 dVRef = sub20_ADC_cmd::dDEFAULT_VOLTREF;
00339 };
00340
00341 Sub20_ADC sub20_ADC_attached(ADC_MUXCONFIG, dRate_Hz, dVRef);
00342 OneSub20_ADC_Meas sOneMeas;
00343 adc_sub20::sub20_ADC_meas msg;
00344 std::list<OneSub20_ADC_Meas> measurements_list;
00345
00347
00349
00350 ros::Rate loop_rate(dRate_Hz);
00351
00352 while (n.ok()) {
00353
00354 try {
00355 sub20_ADC_attached.GetMeasurements(measurements_list, dVRef, &Num_Chans);
00356 }
00357 catch ( std::string strType ) {
00358 std::cout << " An exception occurred: " << strType << std::endl;
00359 std::exit(1);
00360 }
00361
00362 while (!measurements_list.empty()) {
00363 sOneMeas = measurements_list.back ();
00364 measurements_list.pop_back ();
00365
00366 if ( sOneMeas.bMeasAvailable == true ) {
00367 msg.strIdSubDev = sOneMeas.strSerial;
00368
00369
00370 for(int i=0; i<Num_Chans; i++){
00371 msg.uiRaw.push_back(sOneMeas.uiADCRaw[i]);
00372 msg.fVolts.push_back(sOneMeas.fADCVolt[i]);
00373 }
00374 msg.header.stamp = sOneMeas.dtomeas;
00375 sub20_ADC_pub.publish(msg);
00376
00377
00378 msg.uiRaw.clear();
00379 msg.fVolts.clear();
00380 }
00381 }
00382 ros::spinOnce();
00383 loop_rate.sleep();
00384 ++count;
00385 }
00386 }