ArduinoDAQ_LowLevel.cpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2016-17, Universidad de Almeria
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage, Inc. nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 
37 #include <cstring>
38 #include <functional>
39 #include <array>
40 #include <thread>
41 #include <chrono>
42 
43 #ifdef HAVE_ROS
44 #include <ros/console.h>
45 #include <arduino_daq/AnalogReading.h>
46 #include <arduino_daq/EncodersReading.h>
47 #include <arduino_daq/EncoderAbsReading.h>
48 #endif
49 
50 #include <iostream>
51 
52 #include <mrpt/version.h>
53 #if MRPT_VERSION<0x199
54 #include <mrpt/utils/utils_defs.h>
55 using mrpt::utils::VerbosityLevel;
56 using namespace mrpt::utils;
57 #else
58 #include <mrpt/core/format.h>
59 #include <mrpt/core/exceptions.h>
60 #include <mrpt/core/bits_math.h>
61 using mrpt::system::VerbosityLevel;
62 using namespace mrpt::system;
63 using namespace mrpt;
64 #endif
65 
66 
67 using namespace std;
68 using namespace mrpt;
69 
70 #define DEBUG_TRACES
71 
72 #ifdef HAVE_ROS
73 
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)
76 #else
77 void log_callback(const std::string &msg, const VerbosityLevel level, const std::string &loggerName, const mrpt::system::TTimeStamp timestamp)
78 #endif
79 {
80  switch (level)
81  {
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;
86  };
87 }
88 #endif
89 
91  mrpt::utils::COutputLogger("ArduinoDAQ_LowLevel"),
92 #ifdef HAVE_ROS
93  m_nh_params("~"),
94 #endif
95 #ifndef _WIN32
96  m_serial_port_name("/dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0"),
97 #else
98  m_serial_port_name("COM3"),
99 #endif
100  m_serial_port_baudrate(115200)
101 {
102 #ifdef HAVE_ROS
103 #if MRPT_VERSION<0x199
104  this->logRegisterCallback(&log_callback, this);
105 #else
106  this->logRegisterCallback(&log_callback);
107 #endif
108 #endif
109 
110 #ifdef DEBUG_TRACES
111  this->setMinLoggingLevel(LVL_DEBUG);
112 #endif
113 }
114 
116 {
117 }
118 
120 {
121 #ifdef HAVE_ROS
122  m_nh_params.getParam("SERIAL_PORT",m_serial_port_name);
123  m_nh_params.getParam("SERIAL_PORT_BAUDRATE",m_serial_port_baudrate);
124 #endif
125 
126  // Try to connect...
127  if (this->AttemptConnection())
128  {
129  MRPT_LOG_INFO("Connection OK to ArduinoDAQ.");
130  }
131  else
132  {
133  MRPT_LOG_ERROR("Error in ArduinoDAQ_LowLevel::AttemptConnection()!");
134  return false;
135  }
136 
137 #ifdef HAVE_ROS
138  // Subscribers: GPIO outputs
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);
143  }
144 
145  // Subscribers: DAC outputs
146  m_sub_dac.resize(4);
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);
150  }
151 
152 
153  // Subscribers: PWM outputs
154  // (From: https://www.arduino.cc/en/Reference/analogWrite)
155  // On most Arduino boards (those with the ATmega168 or ATmega328), this function works on pins 3, 5, 6, 9, 10, and 11.
156  const int PWM_pins[] = {3, 5, 6, 9, 10, 11};
157  const int num_PWM_pins = sizeof(PWM_pins)/sizeof(PWM_pins[0]);
158 
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);
164  }
165 
166  // Publisher: ADC data
167  m_pub_ADC = m_nh.advertise<arduino_daq::AnalogReading>("arduino_daq_adc", 10);
168 
169  // Publisher: ENC data
170  m_pub_ENC = m_nh.advertise<arduino_daq::EncodersReading>("arduino_daq_encoders", 10);
171 
172  // Publisher: ABS ENC data
173  m_pub_ENC_ABS = m_nh.advertise<arduino_daq::EncoderAbsReading>("arduino_daq_abs_encoder", 10);
174 
175  // Only for ROS:
176  // If provided via params, automatically start ADC conversion:
177  {
178  int ADC_INTERNAL_REFVOLT = 0;
179  m_nh_params.getParam("ADC_INTERNAL_REFVOLT",ADC_INTERNAL_REFVOLT);
180 
181  int ADC_MEASURE_PERIOD_MS = 100;
182  m_nh_params.getParam("ADC_MEASURE_PERIOD_MS",ADC_MEASURE_PERIOD_MS);
183 
185  bool any_active = false;
186  for (int i=0;i<8;i++)
187  {
188  int ch = -1;
189  m_nh_params.getParam(mrpt::format("ADC_CHANNEL%i",i),ch);
190  cmd.active_channels[i] = ch;
191  if (ch!=-1) any_active=true;
192  }
193 
194  if (any_active)
195  {
196  cmd.use_internal_refvolt = ADC_INTERNAL_REFVOLT ? 1:0;
197  cmd.measure_period_ms = ADC_MEASURE_PERIOD_MS;
198 
199  MRPT_LOG_INFO_FMT ("Starting continuous ADC readings with: "
200  "int_ref_volt=%i "
201  "measure_period_ms=%i ms"
202  "channels: %i %i %i %i %i %i %i %i"
203  ,
205  cmd.measure_period_ms,
208  );
209  this->CMD_ADC_START(cmd);
210  }
211  }
212 
213  // If provided via params, automatically start ENCODERS decoding:
214  {
215  std::array<int,TFrameCMD_ENCODERS_start_payload_t::NUM_ENCODERS> ENC_PIN_A,ENC_PIN_B,ENC_PIN_Z;
216  ENC_PIN_A.fill(0);
217  ENC_PIN_B.fill(0);
218  ENC_PIN_Z.fill(0);
219 
220  bool any_active = false;
222  {
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) {
227  any_active = true;
228  }
229  }
230 
231  int ENC_MEASURE_PERIOD_MS = 100;
232  m_nh_params.getParam("ENC_MEASURE_PERIOD_MS",ENC_MEASURE_PERIOD_MS);
233 
236  {
237  cmd.encA_pin[i] = ENC_PIN_A[i];
238  cmd.encB_pin[i] = ENC_PIN_B[i];
239  cmd.encZ_pin[i] = ENC_PIN_Z[i];
240  }
241  if (any_active)
242  {
243  cmd.sampling_period_ms = ENC_MEASURE_PERIOD_MS;
244 
245  MRPT_LOG_INFO("Starting ENCODERS readings with: ");
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]);
248  }
249  this->CMD_ENCODERS_START(cmd);
250  }
251  }
252 
253  // If provided via params, automatically start reading the absolute encoder
254  {
256  int pin_cs=0, pin_clk=0, pin_do=0, sampling_period_ms = 100;
257 
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);
262 
263  if (pin_cs>0 && pin_clk>0 && pin_do>0)
264  {
265  ENC_cfg.ENCODER_ABS_CS = pin_cs;
266  ENC_cfg.ENCODER_ABS_CLK = pin_clk;
267  ENC_cfg.ENCODER_ABS_DO = pin_do;
268  ENC_cfg.sampling_period_ms = sampling_period_ms;
269 
270  MRPT_LOG_INFO_FMT("Starting ABSOLUTE ENCODER readings (period=%i ms) with: ",
271  sampling_period_ms);
272  MRPT_LOG_INFO_FMT(" ENC0: CS_pin=%i CLK_pin=%i DO_pin=%i",pin_cs,
273  pin_clk, pin_do);
274 
275  this->CMD_ENCODER_ABS_START(ENC_cfg);
276  }
277  }
278 
279 #endif
280 
281  return true;
282 }
283 
284 void ArduinoDAQ_LowLevel::processIncommingFrame(const std::vector<uint8_t> &rxFrame)
285 {
286  //MRPT_LOG_INFO_STREAM << "Rx frame, len=" << rxFrame.size();
287  if (rxFrame.size() >= 5)
288  {
289  switch (rxFrame[1])
290  {
291  case RESP_ADC_READINGS:
292  {
294  ::memcpy((uint8_t*)&rx, &rxFrame[0], sizeof(rx));
295 
296  if (m_adc_callback) {
298  }
300  }
301  break;
302 
304  {
306  ::memcpy((uint8_t*)&rx, &rxFrame[0], sizeof(rx));
307 
308  if (m_enc_callback) {
310  }
312  }
313  break;
314 
316  {
318  ::memcpy((uint8_t*)&rx, &rxFrame[0], sizeof(rx));
319 
320  if (m_encabs_callback) {
322  }
324  }
325  break;
326  };
327  }
328 }
329 
331 {
332  // Main module loop code.
333  const size_t MAX_FRAMES_PER_ITERATE = 20;
334  size_t nFrames = 0;
335 
336  if (!m_serial.isOpen())
337  {
338  if (!this->initialize())
339  return false;
340  }
341 
342  std::vector<uint8_t> rxFrame;
343  while (ReceiveFrameFromController(rxFrame) && ++nFrames<MAX_FRAMES_PER_ITERATE)
344  {
345  // Process them:
346  processIncommingFrame(rxFrame);
347  }
348 
349  // if no frame was received, ping the uC to keep comms alive:
350  if (!nFrames && m_NOP_sent_counter++>20)
351  {
353 
354  // Send a dummy NOP command
357  return WriteBinaryFrame(reinterpret_cast<uint8_t*>(&cmd), sizeof(cmd));
358  }
359 
360  return true;
361 }
362 
363 #ifdef HAVE_ROS
364 void ArduinoDAQ_LowLevel::daqSetDigitalPinCallback(int pin, const std_msgs::Bool::ConstPtr& msg)
365 {
366  ROS_INFO("GPIO: output[%i]=%s", pin, msg->data ? "true":"false" );
367 
368  if (!CMD_GPIO_output(pin,msg->data)) {
369  ROS_ERROR("*** Error sending CMD_GPIO_output!!! ***");
370  }
371 }
372 
373 void ArduinoDAQ_LowLevel::daqSetDACCallback(int dac_index, const std_msgs::Float64::ConstPtr& msg)
374 {
375  ROS_INFO("DAC: channel[%i]=%f V", dac_index, msg->data);
376 
377  if (!CMD_DAC(dac_index,msg->data)) {
378  ROS_ERROR("*** Error sending CMD_DAC!!! ***");
379  }
380 
381 }
382 
383 void ArduinoDAQ_LowLevel::daqSetPWMCallback(int pwm_pin_index, const std_msgs::UInt8::ConstPtr& msg)
384 {
385  ROS_INFO("PWM: pin%i=%i ", pwm_pin_index, (int)msg->data);
386 
387  if (!CMD_PWM(pwm_pin_index,msg->data)) {
388  ROS_ERROR("*** Error sending CMD_PWM!!! ***");
389  }
390 }
391 
393 {
394  arduino_daq::AnalogReading msg;
395 
396  msg.timestamp_ms = data.timestamp_ms;
397  for (int i=0;i<sizeof(data.adc_data)/sizeof(data.adc_data[0]);i++) {
398  msg.adc_data[i] = data.adc_data[i];
399  }
400 
401  m_pub_ADC.publish(msg);
402 }
403 
405 {
406  arduino_daq::EncodersReading msg;
407 
408  msg.timestamp_ms = data.timestamp_ms;
409  msg.period_ms = data.period_ms;
410  const int N =sizeof(data.encoders)/sizeof(data.encoders[0]);
411 
412  msg.encoder_values.resize(N);
413  for (int i=0;i<N;i++) {
414  msg.encoder_values[i] = data.encoders[i];
415  }
416 
417  m_pub_ENC.publish(msg);
418 }
419 
421 {
422  arduino_daq::EncoderAbsReading msg;
423 
424  msg.timestamp_ms = data.timestamp_ms;
425  msg.encoder_status = data.enc_status;
426  msg.encoder_value = data.enc_pos;
427 
428  m_pub_ENC_ABS.publish(msg);
429 }
430 
431 
432 #endif
433 
435 {
436  if (m_serial.isOpen()) return true; // Already open.
437 
438  try {
440 
441  // Set basic params:
443  m_serial.setTimeouts(100,0,10,0,50);
444 
445  MRPT_LOG_INFO_FMT("[ArduinoDAQ_LowLevel::AttemptConnection] Serial port '%s' open was successful.", m_serial_port_name.c_str() );
446  return true;
447  }
448  catch (std::exception &e)
449  {
450  MRPT_LOG_ERROR_FMT("[ArduinoDAQ_LowLevel::AttemptConnection] COMMS error: %s", e.what() );
451  return false;
452  }
453 }
454 
455 
457 bool ArduinoDAQ_LowLevel::WriteBinaryFrame(const uint8_t *full_frame, const size_t full_frame_len)
458 {
459  if (!AttemptConnection()) return false;
460 
461  ASSERT_(full_frame!=NULL);
462 
463  try
464  {
465 #ifdef DEBUG_TRACES
466  {
467  std::string s;
468  s+=mrpt::format("TX frame (%u bytes): ", (unsigned int) full_frame_len);
469  for (size_t i=0;i< full_frame_len;i++)
470  s+=mrpt::format("%02X ", full_frame[i]);
471  MRPT_LOG_DEBUG_FMT("Tx frame: %s", s.c_str());
472  }
473 #endif
474 
475 #if MRPT_VERSION<0x199
476  m_serial.WriteBuffer(full_frame,full_frame_len);
477 #else
478  m_serial.Write(full_frame,full_frame_len);
479 #endif
480  return true;
481  }
482  catch (std::exception &)
483  {
484  return false;
485  }
486 }
487 
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
494  )
495 {
496  if (expected_ans_opcode==0 && full_frame_len>2)
497  expected_ans_opcode=full_frame[1]+0x70; // answer OPCODE convention
498 
499  for (int iter=0;iter<num_retries;iter++)
500  {
501  if (iter>0)
502  std::this_thread::sleep_for(std::chrono::milliseconds(retries_interval_ms));
503 
504  // Send:
505  if (!WriteBinaryFrame(full_frame,full_frame_len))
506  continue;
507 
508  // Wait for answer:
509  std::vector<uint8_t> rxFrame;
510  if (this->ReceiveFrameFromController(rxFrame) && rxFrame.size()>4)
511  {
512  const auto RX_OPCODE = rxFrame[1];
513  if (RX_OPCODE==expected_ans_opcode)
514  {
515  // We received the ACK from the uC, yay!
516  MRPT_LOG_DEBUG_FMT("SendFrameAndWaitAnswer(): Rx ACK for OPCODE=0x%02X after %i retries.",full_frame_len>2 ? full_frame[1] : 0, iter);
517  return true;
518  }
519  else
520  {
521  // Ensure the frame gets processed:
522  processIncommingFrame(rxFrame);
523  }
524  }
525  }
526  MRPT_LOG_ERROR_FMT("SendFrameAndWaitAnswer(): Missed ACK for OPCODE=0x%02X",full_frame_len>2 ? full_frame[1] : 0);
527  return false; // No answer!
528 }
529 
530 bool ArduinoDAQ_LowLevel::ReceiveFrameFromController(std::vector<uint8_t> &rxFrame)
531 {
532  rxFrame.clear();
533  size_t nFrameBytes = 0;
534  std::vector<uint8_t> buf;
535  buf.resize(0x10000);
536  buf[0] = buf[1] = 0;
537 
538  size_t lengthField;
539 
540  /*
541  START_FLAG | OPCODE | DATA_LEN | DATA | CHECKSUM | END_FLAG |
542  0x69 1 byte 1 byte N bytes =sum(data) 0x96
543  */
544 
545  // START_FLAG OPCODE + LEN DATA CHECKSUM + END_FLAG
546  while ( nFrameBytes < (lengthField=( 1 + 1 + 1 + buf[2] + 1 + 1 ) ) )
547  {
548  if (lengthField>200)
549  {
550  nFrameBytes = 0; // No es cabecera de trama correcta
551  buf[1]=buf[2]=0;
552  MRPT_LOG_INFO("[rx] Reset frame (invalid len)");
553  }
554 
555  size_t nBytesToRead;
556  if (nFrameBytes<3)
557  nBytesToRead = 1;
558  else
559  nBytesToRead = (lengthField) - nFrameBytes;
560 
561  size_t nRead;
562  try
563  {
564  nRead = m_serial.Read( &buf[0] + nFrameBytes, nBytesToRead );
565  }
566  catch (std::exception &e)
567  {
568  // Disconnected?
569  MRPT_LOG_ERROR_FMT("ReceiveFrameFromController(): Comms error: %s", e.what());
570  return false;
571  }
572 
573  if ( !nRead && !nFrameBytes )
574  {
575  //cout << "[rx] No frame (buffer empty)\n";
576  return false;
577  }
578 
579  if (nRead<nBytesToRead)
580  {
581  using namespace std::chrono_literals;
582  std::this_thread::sleep_for(1ms);
583  }
584 
585  // Reading was OK:
586  // Check start flag:
587  bool is_ok = true;
588 
589  if (!nFrameBytes && buf[0]!= FRAME_START_FLAG )
590  {
591  is_ok = false;
592  MRPT_LOG_DEBUG("[rx] Reset frame (start flag)");
593  }
594 
595  if (nFrameBytes>2 && nFrameBytes+nRead==lengthField)
596  {
597  if (buf[nFrameBytes+nRead-1]!=FRAME_END_FLAG)
598  {
599  is_ok= false;
600  MRPT_LOG_DEBUG("[rx] Reset frame (end flag)");
601  }
602  }
603 
604  MRPT_TODO("Checksum");
605 
606  if (is_ok)
607  {
608  nFrameBytes+=nRead;
609  }
610  else
611  {
612  nFrameBytes = 0; // No es cabecera de trama correcta
613  buf[1]=buf[2]=0;
614  }
615  }
616 
617  // Frame received
618  lengthField= buf[2]+5;
619  rxFrame.resize(lengthField);
620  ::memcpy( &rxFrame[0], &buf[0], lengthField);
621 
622 #ifdef DEBUG_TRACES
623  {
624  std::string s;
625  s+=mrpt::format("RX frame (%u bytes): ", (unsigned int) lengthField);
626  for (size_t i=0;i< lengthField;i++)
627  s+=mrpt::format("%02X ", rxFrame[i]);
628  MRPT_LOG_DEBUG_FMT("%s", s.c_str());
629  }
630 #endif
631 
632  // All OK
633  return true;
634 }
635 
636 
637 bool ArduinoDAQ_LowLevel::CMD_GPIO_output(int pin, bool pinState)
638 {
640  cmd.payload.pin_index = pin;
641  cmd.payload.pin_value = pinState ? 1:0;
642 
644 
645  return SendFrameAndWaitAnswer(reinterpret_cast<uint8_t*>(&cmd),sizeof(cmd));
646 }
647 
649 bool ArduinoDAQ_LowLevel::CMD_DAC(int dac_index,double dac_value_volts)
650 {
651  uint16_t dac_counts = 4096 * dac_value_volts / 5.0;
652  saturate(dac_counts, uint16_t(0), uint16_t(4095));
653 
655  cmd.payload.dac_index = dac_index;
656  cmd.payload.dac_value_HI = dac_counts >> 8;
657  cmd.payload.dac_value_LO = dac_counts & 0x00ff;
658  cmd.payload.flag_enable_timeout = true;
659 
661 
662  return SendFrameAndWaitAnswer(reinterpret_cast<uint8_t*>(&cmd),sizeof(cmd));
663 }
664 
666 {
667  return m_serial.isOpen();
668 }
669 
671 {
673  cmd.payload = adc_config;
675 
676  return SendFrameAndWaitAnswer(reinterpret_cast<uint8_t*>(&cmd), sizeof(cmd));
677 }
679 {
682 
683  return SendFrameAndWaitAnswer(reinterpret_cast<uint8_t*>(&cmd), sizeof(cmd));
684 }
685 
687 {
689  cmd.payload = enc_config;
691 
692  return SendFrameAndWaitAnswer(reinterpret_cast<uint8_t*>(&cmd), sizeof(cmd));
693 }
695 {
698 
699  return SendFrameAndWaitAnswer(reinterpret_cast<uint8_t*>(&cmd), sizeof(cmd));
700 }
701 
703 {
705  cmd.payload = enc_config;
707 
708  return SendFrameAndWaitAnswer(reinterpret_cast<uint8_t*>(&cmd), sizeof(cmd));
709 }
711 {
714 
715  return SendFrameAndWaitAnswer(reinterpret_cast<uint8_t*>(&cmd), sizeof(cmd));
716 }
717 
718 bool ArduinoDAQ_LowLevel::CMD_PWM(int pin_index, uint8_t pwm_value)
719 {
721  cmd.payload.pin_index = pin_index;
722  cmd.payload.analog_value = pwm_value;
723  cmd.payload.flag_enable_timeout = true;
725 
726  return SendFrameAndWaitAnswer(reinterpret_cast<uint8_t*>(&cmd), sizeof(cmd));
727 }
void daqOnNewADCCallback(const TFrame_ADC_readings_payload_t &data)
uint64_t TTimeStamp
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.
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)
#define ROS_WARN(...)
MRPT_TODO("Modify ping to run on Windows + Test this")
#define N(a, b, c)
GLdouble s
#define MRPT_LOG_DEBUG_FMT(_FMT_STRING,...)
uint8_t enc_status
See EMS22A datasheet for the bit map.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
#define ROS_INFO(...)
void daqOnNewENCAbsCallback(const TFrame_ENCODER_ABS_reading_payload_t &data)
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
#define FRAME_START_FLAG
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)
GLint level
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
#define MRPT_LOG_INFO_FMT(_FMT_STRING,...)
bool CMD_PWM(int pin_index, uint8_t pwm_value)
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)
#define ASSERT_(f)
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)
#define ROS_ERROR(...)
bool ReceiveFrameFromController(std::vector< uint8_t > &rx_data)
Tries to get a framed chunk of data from the controller.
#define FRAME_END_FLAG
#define ROS_DEBUG(...)


arduino_daq
Author(s):
autogenerated on Mon Jun 10 2019 12:46:03