66 #include <sys/ioctl.h> 67 #include <linux/serial.h> 70 #include <arpa/inet.h> 108 std::cout <<
"ATIForceTorqueSensorHWRS485::initCommunication" << std::endl;
112 std::cout <<
"Baudrate " << baudrate <<
" is not supported!" << std::endl;
127 std::cout <<
"ATIForceTorqueSensorHWRS485::init" << std::endl;
140 std::cout <<
"Can not read Calibration Data from FTS!" << std::endl;
168 std::cout <<
"RS485 initialization unsuccessful!" << std::endl;
178 std::cout <<
"ATIForceTorqueSensorHWRS485::initRS485" << std::endl;
192 bool gotStatusWord =
false;
193 while (!gotStatusWord && tries < 10) {
197 std::cout <<
"Could not initialize modbus connection" << std::endl;
210 std::cout <<
"Could not set slave ID" << std::endl;
219 std::cout <<
"Could not connect" << std::endl;
243 std::cout <<
"Could not read status word!" << std::endl;
253 std::cout <<
"\n\n*********FTSerialNumber**********" << std::endl;
255 if (calibrationNumber < 1 || calibrationNumber > 16)
257 std::cout <<
"Invalid calibration number" << std::endl;
261 uint16_t tab_reg[168];
262 unsigned int registerOffset = (calibrationNumber - 1) * 192;
272 std::cout <<
"Reading Calibration Data failed" << std::endl;
277 std::string calibSerialNumber;
278 for (
unsigned int i = 0; i < 4; i++)
287 std::string calibPartNumber;
288 for (
unsigned int i = 4; i < 20; i++)
298 std::string calibFamilyID;
299 for (
unsigned int i = 20; i < 22; i++)
309 std::string calibTime;
310 for (
unsigned int i = 22; i < 32; i++)
320 std::cout <<
"Calibration Matrix:" << std::endl;
321 for (
unsigned int i = 0; i < 6; i++)
323 for (
unsigned int j = 0; j < 6; j++)
325 unsigned int index = 32+(i*6+j)*2;
331 std::cout << std::endl;
336 std::cout <<
"Force Units are ";
340 std::cout <<
"Pound" << std::endl;
343 std::cout <<
"Newton" << std::endl;
346 std::cout <<
"Kilopound" << std::endl;
349 std::cout <<
"KiloNewton" << std::endl;
352 std::cout <<
"Kilogram-equivalent force" << std::endl;
355 std::cout <<
"Gram-equivalent force" << std::endl;
358 std::cout <<
"Unknown!" << std::endl;
366 std::cout <<
"Torque Units are ";
370 std::cout <<
"Pound-inch" << std::endl;
373 std::cout <<
"Pound-foot" << std::endl;
376 std::cout <<
"Newton-meter" << std::endl;
379 std::cout <<
"Newton-millimeter" << std::endl;
382 std::cout <<
"Kilogram(-equivalent)-centimeter" << std::endl;
385 std::cout <<
"Unknown!" << std::endl;
391 for (
unsigned int i = 0; i < 6; i++)
393 unsigned int index = 105 +i*2;
395 temp = (((int32_t)tab_reg[index]) << 16) | tab_reg[index+1];
406 for (
unsigned int i = 0; i < 6; i++)
413 for (
unsigned int i = 0; i < 6; i++)
443 std::cout <<
"Could not set storage lock. No confirmation received." << std::endl;
448 std::cout <<
"Could not set storage lock. Invalid answer." << std::endl;
452 std::cout <<
"Setting storage lock was successful" << std::endl;
462 std::cout <<
"Setting active gain to " << ag0 <<
", " << ag1 <<
", " << ag2 <<
", " << ag3 <<
", " << ag4 <<
", " << ag5 << std::endl;
464 uint16_t activeGain[6] = {ag0, ag1, ag2, ag3, ag4, ag5};
468 std::cout <<
"Setting active gain failed with status " << rc << std::endl;
479 std::cout <<
"Setting active offset to " << ao0 <<
", " << ao1 <<
", " << ao2 <<
", " << ao3 <<
", " << ao4 <<
", " << ao5 << std::endl;
481 uint16_t activeOffset[6] = {ao0, ao1, ao2, ao3, ao4, ao5};
485 std::cout <<
"Setting active offset failed with status " << rc << std::endl;
495 std::cout <<
"\n\n*********FTStatusWord**********" << std::endl;
502 std::cout <<
"Reading Status Word failed with status " << rc << std::endl;
506 bool statusGood =
true;
510 std::cout <<
"Status is good." << std::endl;
517 std::cout <<
"Watchdog reset - the analog board was reset by the watchdog timer." << std::endl;
521 std::cout <<
"Excitation voltage too high." << std::endl;
525 std::cout <<
"Excitation voltage too low." << std::endl;
529 std::cout <<
"Artificial analog ground out of range." << std::endl;
533 std::cout <<
"Power supply too high." << std::endl;
537 std::cout <<
"Power supply too low." << std::endl;
541 std::cout <<
"Error accessing stored settings in EEPROM." << std::endl;
545 std::cout <<
"Invalid configuration data." << std::endl;
549 std::cout <<
"Strain gage bridge supply current too high." << std::endl;
553 std::cout <<
"Strain gage bridge supply current too low." << std::endl;
557 std::cout <<
"Thermistor too high." << std::endl;
561 std::cout <<
"Thermistor too low." << std::endl;
565 std::cout <<
"DAC reading out of range." << std::endl;
573 std::cout <<
"\n\n*******Setting Baud Rate value to: " << value <<
"********" << std::endl;
575 uint16_t baudrateIndex = 0;
590 fprintf(
stderr,
"Baudrate %i is not supported \n", value);
597 uint16_t tab_reg[1] = {1};
602 std::cout <<
"Setting non-volatile baud rate flag failed with status " << rc << std::endl;
608 uint16_t tab_reg[1] = {baudrateIndex};
613 std::cout <<
"Setting baudrate failed with status " << rc << std::endl;
627 std::cout <<
"\n\n******* Reseting the RS485 Interface ********" << std::endl;
651 std::cout <<
"\n\n*******Setting Session ID value to HEX : " << std::hex << sessionID <<
" ********" << std::endl;
653 uint16_t tab_reg[1] = {sessionID};
659 std::cout <<
"Setting Session ID failed with status " << rc << std::endl;
670 std::cout <<
"\n\n*******Reading Session ID"<<
" ********" 679 std::cout <<
"Reading Session ID failed with status " << rc << std::endl;
684 sessionID = tab_reg[0];
691 int sg0 = 0, sg1 = 0, sg2 = 0, sg3 = 0, sg4 = 0, sg5 = 0;
704 std::cout <<
"Buffer timestamp is too far in the past! Data might be deprecated and will be ignored. (" << timeSinceLastInput <<
")" << std::endl;
733 std::cout <<
"Trying to start stream" << std::endl;
744 std::cout <<
"Could not start data streaming. No confirmation received." << std::endl;
747 else if (rsp[2] == 1)
757 std::cout <<
"Could not start data streaming. Invalid answer." << std::endl;
761 std::cout <<
"Started streaming." << std::endl;
779 std::cout <<
"Error " << errno <<
" opening " <<
m_RS485Device <<
": " << strerror (errno) << std::endl;
785 struct serial_struct ss;
786 ioctl(
m_rs485, TIOCGSERIAL, &ss);
787 ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
789 int closestSpeed = ss.baud_base / ss.custom_divisor;
791 if (closestSpeed < m_ModbusBaudrate * 98 / 100 || closestSpeed >
m_ModbusBaudrate * 102 / 100) {
792 fprintf(
stderr,
"Cannot set serial port speed to. Closest possible is %i\n", closestSpeed);
795 ioctl(
m_rs485, TIOCSSERIAL, &ss);
797 memset(&tios, 0,
sizeof(
struct termios));
800 cfsetispeed(&tios, B38400);
801 cfsetospeed(&tios, B38400);
803 if ((cfsetispeed(&tios, speed) < 0) ||
804 (cfsetospeed(&tios, speed) < 0)) {
807 std::cout <<
"Could not set speed" << std::endl;
811 ioctl(
m_rs485, TIOCSSERIAL, &ss);
813 tios.c_iflag &= ~(IXON | IXOFF | IXANY);
815 tios.c_oflag &=~ OPOST;
816 tios.c_cflag &= ~CSIZE;
818 tios.c_cflag &=~ CSTOPB;
819 tios.c_cflag |= PARENB;
820 tios.c_cflag &=~ PARODD;
821 tios.c_iflag |= INPCK;
822 tios.c_cflag |= (CREAD | CLOCAL);
823 tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
824 tios.c_cc[VMIN] = 39;
825 tios.c_cc[VTIME] = 0;
826 if (tcsetattr(
m_rs485, TCSANOW, &tios) < 0)
843 std::cout <<
"Error while reading: Timeout. " << std::endl;
845 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
865 std::cout <<
"Error reading: " << strerror(errno) << std::endl;
866 std::chrono::microseconds sleepTime = std::chrono::microseconds(5000);
871 std::cout <<
"No data received!" << std::endl;
872 std::chrono::microseconds sleepTime = std::chrono::microseconds(5000);
877 std::cout <<
"Data truncated. n: " << n <<
" bufferSize: " <<
bufferSize << std::endl;
916 if (((check >> 7) & 0x01))
919 std::cout <<
bytesRead <<
"Invalid status bit" << std::endl;
922 uint8_t checksum = check & 0x7F;
924 int compareChecksum = 0;
925 for (
unsigned int i = 0; i < 12; i++)
927 compareChecksum += buf[i];
929 if ((compareChecksum & 0x7F) != checksum)
931 std::cout <<
bytesRead <<
"Package has invalid checksum! Ignoring data... ";
956 unsigned char stopCmd[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
957 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
958 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
959 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
963 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
964 int n_written = write(
m_rs485, stopCmd,
sizeof(stopCmd));
972 Eigen::VectorXf v6SG(6);
973 Eigen::VectorXf tmp(6);
994 Eigen::MatrixXf tmp(6, 6);
995 for (
unsigned int i = 0; i < 6; i++)
997 for (
unsigned int j = 0; j < 6; j++)
999 tmp(i,j) = matrix[i][j];
#define MODBUS_GET_LOW_BYTE(data)
std::string calibFamilyID
#define ST_THERMISTOR_HIGH
int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length)
#define ST_DAC_READING_OOR
#define ST_EXC_VOLTAGE_LOW
int modbus_set_slave(modbus_t *ctx, int slave)
int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
#define ST_STRAIN_GAGE_SUPPLY_HIGH
long unsigned int bytesRead
#define MODBUS_RTU_MAX_ADU_LENGTH
virtual bool readFTData(int statusCode, double &Fx, double &Fy, double &Fz, double &Tx, double &Ty, double &Tz)
std::string calibPartNumberNumber
bool ReadSessionID(uint16_t &sessionID) const
#define ST_STRAIN_GAGE_SUPPLY_LOW
int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src)
#define ST_WATCHDOG_RESET
boost::thread m_readThread
bool ReadFTCalibrationData(const unsigned int calibrationNumber=1)
const std::string TorqueUnitNames[]
#define MODBUSBAUD_115200
virtual ~ATIForceTorqueSensorHWRS485()
void StrainGaugeToForce(const int &sg0, const int &sg1, const int &sg2, const int &sg3, const int &sg4, const int &sg5)
void SetCalibMatrix(const float(&matrix)[6][6])
const char * modbus_strerror(int errnum)
CalibrationData m_calibrationData
#define MODBUS_GET_INT32_FROM_INT16(tab_int16, index)
#define MODBUS_GET_HIGH_BYTE(data)
bool SetSessionID(const uint16_t sessionID)
uint8_t m_ModbusBaseIdentifier
const std::string ForceUnitNames[]
bool SetStorageLock(const bool lock) const
std::mutex m_buffer_mutex
Eigen::MatrixXf m_vForceData
ATIForceTorqueSensorHWRS485()
#define ST_ART_ANALOG_GRND_OOR
bool SetBaudRate(const int value, const bool setVolatile=true)
#define ST_THERMISTOR_LOW
bool ReadStatusWord() const
long unsigned int m_bufferTimeout
Eigen::MatrixXf m_mXCalibMatrix
ros::Time lastValidTimeStamp
bool ValidateFTData(const uint8_t(&buf)[26]) const
std::string calibSerialNumber
TorqueUnit torqueUnitsInt
virtual bool initCommunication(int type, std::string path, int baudrate, int base_identifier)
int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp)
void modbus_close(modbus_t *ctx)
bool SetActiveOffset(const uint16_t ao0, const uint16_t ao1, const uint16_t ao2, const uint16_t ao3, const uint16_t ao4, const uint16_t ao5) const
std::string m_RS485Device
modbus_t * modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit)
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
void modbus_free(modbus_t *ctx)
int modbus_connect(modbus_t *ctx)
std::string torqueUnitStr
#define ST_EXC_VOLTAGE_HIGH
bool SetActiveGain(const uint16_t ag0, const uint16_t ag1, const uint16_t ag2, const uint16_t ag3, const uint16_t ag4, const uint16_t ag5) const