Equivalent implementation of HardwareSerial


I am looking at converting part of a ROS serial communications library http://www.ros.org/wiki/rosserial to reduce some of the boilerplate serial message passing/receiving setup while still using the pololu avr libraries instead of Arduino.

Currently the code looks to be modular enough that if I can rewrite the implementation of HardwareSerial.h for arduino to the equivalent SVP version, I could start testing. I have read that it’s preferrable to use SoftwareSerial (because I might accidentally reprogram the board?) so I could maybe test that first instead. I am seeking suggestions on how (and whether) to proceed. Thanks in advance

If you can install the right interrupt handlers (for transmit-underflow and received-data) then driving the serial port of an AVR microcontroller is easy.
Especially if you can hard-code the baud rate setup, because then you don’t need a table or math to get the baud rate to configuration register settings.
I got a lot more effective when I shed the shackles of pre-canned libraries (like the Arduino library) and just use those libraries for documentation/inspiration.
A data sheet and a good compiler is your best friend :slight_smile:

Thanks, writing low-level code isn’t exactly my specialty, so I wanted to make sure I wouldn’t be starting something I would learn to regret :).

I do have the tools I need to get moving so I will start reading the datasheet and give it a shot. If there are any references or templates I could look at to give me a start I would appreciate it, otherwise I think I will have to read arduino datasheets as well to understand what each command is doing.

The Atmega data sheets from Atmel are actually very good. They even contain code examples for how to do set-up, transmit, and receive (in the UART chapter.) They use the Atmel C library, so if you’re using GCC, there’s a little bit of renaming to do, but I find it a joy to use, compared to some other chip vendors that should be left unnamed :slight_smile:

Thanks for your help. After digging a bit deeper, I saw that rosserial_client does support arbitrary hardware http://www.ros.org/wiki/rosserial_client/Tutorials/Adding%20Support%20for%20New%20Hardware, provided you define the templated Hardware interface.

The example given http://www.ros.org/wiki/rosserial_client/Tutorials/Using%20rosserial%20with%20AVR%20and%20UART shows an example using UART, but with my SVP, I wanted to use the existing pololu-avr library tools and communicate over the USB_COMM port.

After modifying the Makefile, the final function for sending “Hello World” as a ROS message from the SVP1284 to a ROS environment was achieved with the following code. Hopefully this helps somebody down the line-- the advantage of this route is that there is no longer any worries about defining and modifying a message as you develop, then having to rewrite the message sending and parsing functions.

#ifndef _SVP1284_HARDWARE_H
#define _SVP1284_HARDWARE_H

extern "C"
  #include <pololu/orangutan.h>

#define port USB_COMM

class svp1284Hardware {
    svp1284Hardware(): receive_buffer_position_(0) {}

    // Initialize the AVR
    void init()
      OrangutanTime::ms();// If not already called, this will call private function init()
      OrangutanSerial::receiveRing(port, receive_buffer_, sizeof(receive_buffer_));

    // Read a byte of data from ROS connection.
    // If no data, returns -1
    int read()
      if (OrangutanSerial::getReceivedBytes(port)!= receive_buffer_position_)
        b=(unsigned char)receive_buffer_[receive_buffer_position_];
        return b;
          return -1;

    // Send bytes of data to ROS connection
    void write(uint8_t* data, int length)
      OrangutanSerial::send(port,(char*) data,length);

    // Returns milliseconds since start of program
    unsigned long time()
      return OrangutanTime::ms();

    char receive_buffer_[128];
    unsigned char receive_buffer_position_;
    unsigned char b;

    void increment_buffer_pos()
      // Increment receive_buffer_position, but wrap around when it gets to
      // the end of the buffer.
      if (receive_buffer_position_ == sizeof(receive_buffer_)-1)
        receive_buffer_position_ = 0;