45 #include <arduino_daq/AnalogReading.h> 46 #include <arduino_daq/EncodersReading.h> 47 #include <arduino_daq/EncoderAbsReading.h> 52 #include <mrpt/version.h> 53 #if MRPT_VERSION<0x199 55 using mrpt::utils::VerbosityLevel;
58 #include <mrpt/core/format.h> 59 #include <mrpt/core/exceptions.h> 60 #include <mrpt/core/bits_math.h> 61 using mrpt::system::VerbosityLevel;
74 #if MRPT_VERSION<0x199 75 void log_callback(
const std::string &msg,
const VerbosityLevel
level,
const std::string &loggerName,
const mrpt::system::TTimeStamp timestamp,
void *userParam)
77 void log_callback(
const std::string &msg,
const VerbosityLevel level,
const std::string &loggerName,
const mrpt::system::TTimeStamp timestamp)
82 case LVL_DEBUG:
ROS_DEBUG(
"%s",msg.c_str());
break;
83 case LVL_INFO:
ROS_INFO(
"%s",msg.c_str());
break;
84 case LVL_WARN:
ROS_WARN(
"%s",msg.c_str());
break;
85 case LVL_ERROR:
ROS_ERROR(
"%s",msg.c_str());
break;
91 mrpt::utils::COutputLogger(
"ArduinoDAQ_LowLevel"),
96 m_serial_port_name(
"/dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0"),
98 m_serial_port_name(
"COM3"),
100 m_serial_port_baudrate(115200)
103 #if MRPT_VERSION<0x199 104 this->logRegisterCallback(&log_callback,
this);
106 this->logRegisterCallback(&log_callback);
111 this->setMinLoggingLevel(LVL_DEBUG);
133 MRPT_LOG_ERROR(
"Error in ArduinoDAQ_LowLevel::AttemptConnection()!");
139 m_sub_GPIO_outputs.resize(13);
140 for (
int i=0;i<13;i++) {
141 auto fn = boost::bind(&ArduinoDAQ_LowLevel::daqSetDigitalPinCallback,
this, i, _1);
142 m_sub_GPIO_outputs[i] = m_nh.subscribe<std_msgs::Bool>(
mrpt::format(
"arduino_daq_GPIO_output%i",i), 10, fn);
147 for (
int i=0;i<4;i++) {
148 auto fn = boost::bind(&ArduinoDAQ_LowLevel::daqSetDACCallback,
this, i, _1);
149 m_sub_dac[i] = m_nh.subscribe<std_msgs::Float64>(
mrpt::format(
"arduino_daq_dac%i",i), 10, fn);
156 const int PWM_pins[] = {3, 5, 6, 9, 10, 11};
157 const int num_PWM_pins =
sizeof(PWM_pins)/
sizeof(PWM_pins[0]);
159 m_sub_PWM_outputs.resize(num_PWM_pins);
160 for (
int i=0;i<num_PWM_pins;i++) {
161 int pin = PWM_pins[i];
162 auto fn = boost::bind(&ArduinoDAQ_LowLevel::daqSetPWMCallback,
this, pin, _1);
163 m_sub_PWM_outputs[i] = m_nh.subscribe<std_msgs::UInt8>(
mrpt::format(
"arduino_daq_pwm%i",pin), 10, fn);
167 m_pub_ADC = m_nh.advertise<arduino_daq::AnalogReading>(
"arduino_daq_adc", 10);
170 m_pub_ENC = m_nh.advertise<arduino_daq::EncodersReading>(
"arduino_daq_encoders", 10);
173 m_pub_ENC_ABS = m_nh.advertise<arduino_daq::EncoderAbsReading>(
"arduino_daq_abs_encoder", 10);
178 int ADC_INTERNAL_REFVOLT = 0;
179 m_nh_params.getParam(
"ADC_INTERNAL_REFVOLT",ADC_INTERNAL_REFVOLT);
181 int ADC_MEASURE_PERIOD_MS = 100;
182 m_nh_params.getParam(
"ADC_MEASURE_PERIOD_MS",ADC_MEASURE_PERIOD_MS);
185 bool any_active =
false;
186 for (
int i=0;i<8;i++)
189 m_nh_params.getParam(
mrpt::format(
"ADC_CHANNEL%i",i),ch);
191 if (ch!=-1) any_active=
true;
201 "measure_period_ms=%i ms" 202 "channels: %i %i %i %i %i %i %i %i" 215 std::array<int,TFrameCMD_ENCODERS_start_payload_t::NUM_ENCODERS> ENC_PIN_A,ENC_PIN_B,ENC_PIN_Z;
220 bool any_active =
false;
223 m_nh_params.getParam(
mrpt::format(
"ENC%i_PIN_A",i),ENC_PIN_A[i]);
224 m_nh_params.getParam(
mrpt::format(
"ENC%i_PIN_B",i),ENC_PIN_B[i]);
225 m_nh_params.getParam(
mrpt::format(
"ENC%i_PIN_Z",i),ENC_PIN_Z[i]);
226 if (ENC_PIN_A[i]!=0) {
231 int ENC_MEASURE_PERIOD_MS = 100;
232 m_nh_params.getParam(
"ENC_MEASURE_PERIOD_MS",ENC_MEASURE_PERIOD_MS);
247 MRPT_LOG_INFO_FMT(
" ENC%i: A_pin=%i B_pin=%i Z_pin=%i",i,ENC_PIN_A[i],ENC_PIN_B[i],ENC_PIN_Z[i]);
256 int pin_cs=0, pin_clk=0, pin_do=0, sampling_period_ms = 100;
258 m_nh_params.getParam(
"ENCABS0_PIN_CS", pin_cs);
259 m_nh_params.getParam(
"ENCABS0_PIN_CLK",pin_clk);
260 m_nh_params.getParam(
"ENCABS0_PIN_DO",pin_do);
261 m_nh_params.getParam(
"ENCABS_MEASURE_PERIOD_MS",sampling_period_ms);
263 if (pin_cs>0 && pin_clk>0 && pin_do>0)
287 if (rxFrame.size() >= 5)
294 ::memcpy((uint8_t*)&rx, &rxFrame[0],
sizeof(rx));
306 ::memcpy((uint8_t*)&rx, &rxFrame[0],
sizeof(rx));
318 ::memcpy((uint8_t*)&rx, &rxFrame[0],
sizeof(rx));
333 const size_t MAX_FRAMES_PER_ITERATE = 20;
342 std::vector<uint8_t> rxFrame;
364 void ArduinoDAQ_LowLevel::daqSetDigitalPinCallback(
int pin,
const std_msgs::Bool::ConstPtr& msg)
366 ROS_INFO(
"GPIO: output[%i]=%s", pin, msg->data ?
"true":
"false" );
369 ROS_ERROR(
"*** Error sending CMD_GPIO_output!!! ***");
373 void ArduinoDAQ_LowLevel::daqSetDACCallback(
int dac_index,
const std_msgs::Float64::ConstPtr& msg)
375 ROS_INFO(
"DAC: channel[%i]=%f V", dac_index, msg->data);
377 if (!
CMD_DAC(dac_index,msg->data)) {
378 ROS_ERROR(
"*** Error sending CMD_DAC!!! ***");
383 void ArduinoDAQ_LowLevel::daqSetPWMCallback(
int pwm_pin_index,
const std_msgs::UInt8::ConstPtr& msg)
385 ROS_INFO(
"PWM: pin%i=%i ", pwm_pin_index, (
int)msg->data);
387 if (!
CMD_PWM(pwm_pin_index,msg->data)) {
388 ROS_ERROR(
"*** Error sending CMD_PWM!!! ***");
394 arduino_daq::AnalogReading msg;
401 m_pub_ADC.publish(msg);
406 arduino_daq::EncodersReading msg;
412 msg.encoder_values.resize(N);
413 for (
int i=0;i<N;i++) {
414 msg.encoder_values[i] = data.
encoders[i];
417 m_pub_ENC.publish(msg);
422 arduino_daq::EncoderAbsReading msg;
426 msg.encoder_value = data.
enc_pos;
428 m_pub_ENC_ABS.publish(msg);
448 catch (std::exception &e)
450 MRPT_LOG_ERROR_FMT(
"[ArduinoDAQ_LowLevel::AttemptConnection] COMMS error: %s", e.what() );
468 s+=
mrpt::format(
"TX frame (%u bytes): ", (
unsigned int) full_frame_len);
469 for (
size_t i=0;i< full_frame_len;i++)
475 #if MRPT_VERSION<0x199 482 catch (std::exception &)
489 const uint8_t *full_frame,
490 const size_t full_frame_len,
491 const int num_retries,
492 const int retries_interval_ms,
493 uint8_t expected_ans_opcode
496 if (expected_ans_opcode==0 && full_frame_len>2)
497 expected_ans_opcode=full_frame[1]+0x70;
499 for (
int iter=0;iter<num_retries;iter++)
502 std::this_thread::sleep_for(std::chrono::milliseconds(retries_interval_ms));
509 std::vector<uint8_t> rxFrame;
512 const auto RX_OPCODE = rxFrame[1];
513 if (RX_OPCODE==expected_ans_opcode)
516 MRPT_LOG_DEBUG_FMT(
"SendFrameAndWaitAnswer(): Rx ACK for OPCODE=0x%02X after %i retries.",full_frame_len>2 ? full_frame[1] : 0, iter);
526 MRPT_LOG_ERROR_FMT(
"SendFrameAndWaitAnswer(): Missed ACK for OPCODE=0x%02X",full_frame_len>2 ? full_frame[1] : 0);
533 size_t nFrameBytes = 0;
534 std::vector<uint8_t> buf;
546 while ( nFrameBytes < (lengthField=( 1 + 1 + 1 + buf[2] + 1 + 1 ) ) )
559 nBytesToRead = (lengthField) - nFrameBytes;
564 nRead =
m_serial.
Read( &buf[0] + nFrameBytes, nBytesToRead );
566 catch (std::exception &e)
573 if ( !nRead && !nFrameBytes )
579 if (nRead<nBytesToRead)
581 using namespace std::chrono_literals;
582 std::this_thread::sleep_for(1ms);
595 if (nFrameBytes>2 && nFrameBytes+nRead==lengthField)
618 lengthField= buf[2]+5;
619 rxFrame.resize(lengthField);
620 ::memcpy( &rxFrame[0], &buf[0], lengthField);
625 s+=
mrpt::format(
"RX frame (%u bytes): ", (
unsigned int) lengthField);
626 for (
size_t i=0;i< lengthField;i++)
651 uint16_t dac_counts = 4096 * dac_value_volts / 5.0;
652 saturate(dac_counts, uint16_t(0), uint16_t(4095));
void daqOnNewADCCallback(const TFrame_ADC_readings_payload_t &data)
void BASE_IMPEXP memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) MRPT_NO_THROWS
void calc_and_update_checksum()
bool CMD_GPIO_output(int pin, bool pinState)
Sets the clutch.
int8_t encA_pin[NUM_ENCODERS]
virtual ~ArduinoDAQ_LowLevel()
bool AttemptConnection()
Returns true if connected OK, false on error.
size_t Read(void *Buffer, size_t Count)
TCLAP::CmdLine cmd("carmen2rawlog", ' ', MRPT_getVersion().c_str())
#define MRPT_LOG_ERROR(_STRING)
void WriteBuffer(const void *Buffer, size_t Count)
bool CMD_ADC_START(const TFrameCMD_ADC_start_payload_t &enc_config)
bool SendFrameAndWaitAnswer(const uint8_t *full_frame, const size_t full_frame_len, const int num_retries=10, const int retries_interval_ms=40, uint8_t expected_ans_opcode=0)
Sends a binary packet, in the expected format (returns false on COMMS error)
bool IsConnected() const
Returns true if the serial comms are working.
#define MRPT_LOG_ERROR_FMT(_FMT_STRING,...)
uint16_t enc_pos
Absolute value read from the encoder (10 bits resolution)
void saturate(T &var, const T sat_min, const T sat_max)
void daqOnNewENCCallback(const TFrame_ENCODERS_readings_payload_t &data)
uint8_t analog_value
0-255 maps to 0% to 100% duty cycle
#define MRPT_LOG_DEBUG(_STRING)
bool CMD_DAC(int dac_index, double dac_value_volts)
uint16_t sampling_period_ms
uint8_t flag_enable_timeout
MRPT_TODO("Modify ping to run on Windows + Test this")
int8_t active_channels[8]
#define MRPT_LOG_DEBUG_FMT(_FMT_STRING,...)
uint8_t enc_status
See EMS22A datasheet for the bit map.
int m_serial_port_baudrate
static const uint8_t NUM_ENCODERS
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
uint8_t flag_enable_timeout
int8_t encZ_pin[NUM_ENCODERS]
void daqOnNewENCAbsCallback(const TFrame_ENCODER_ABS_reading_payload_t &data)
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
bool CMD_ENCODER_ABS_STOP()
std::function< void(TFrame_ADC_readings_payload_t)> m_adc_callback
std::function< void(TFrame_ENCODER_ABS_reading_payload_t)> m_encabs_callback
bool CMD_ENCODER_ABS_START(const TFrameCMD_EMS22A_start_payload_t &enc_config)
void setTimeouts(int ReadIntervalTimeout, int ReadTotalTimeoutMultiplier, int ReadTotalTimeoutConstant, int WriteTotalTimeoutMultiplier, int WriteTotalTimeoutConstant)
CSerialPort m_serial
The serial COMMS object.
bool CMD_ENCODERS_START(const TFrameCMD_ENCODERS_start_payload_t &enc_config)
std::function< void(TFrame_ENCODERS_readings_payload_t)> m_enc_callback
std::string m_serial_port_name
#define MRPT_LOG_INFO_FMT(_FMT_STRING,...)
int8_t encB_pin[NUM_ENCODERS]
bool CMD_PWM(int pin_index, uint8_t pwm_value)
uint16_t sampling_period_ms
bool WriteBinaryFrame(const uint8_t *full_frame, const size_t full_frame_len)
Sends a binary packet, in the expected format (returns false on COMMS error)
uint8_t use_internal_refvolt
0 or 1. Default=0
#define MRPT_LOG_INFO(_STRING)
void setConfig(int baudRate, int parity=0, int bits=8, int nStopBits=1, bool enableFlowControl=false)
size_t Write(const void *Buffer, size_t Count)
uint16_t measure_period_ms
Default = 200.
void processIncommingFrame(const std::vector< uint8_t > &rxFrame)
bool ReceiveFrameFromController(std::vector< uint8_t > &rx_data)
Tries to get a framed chunk of data from the controller.