Sending serial commands through USB host shield help

Hi,

I will try and be as thorough as possible in describing my quandary.

I need to send serial (RS-232) commands from an automation control system (Crestron) to a photo spectrometer that only has a USB connection for power and communications.

I am using an Arduino Mega 2560, an Arduino USB host shield, and a spark fun RS-232 board that are connected to Tx/Rx3 (pin 14 & 15).

Using some codes that I’ve pilfered from available examples, I seem to have made a halfway working system. I can use the Arduino serial monitor to send the commands to the USB device and get the data to display in that window. I can also get that information to display in a second serial monitor window that i’ve setup by attaching the output of the spark fun RS-232 to my computer using a keyspan USB/RS232 adapter. What I cannot do is send commands from the second serial monitor through the arduino and to the attached spectrometer.

If anyone has any pearls of wisdom to shed on my quandary it would be greatly appreciated.

Thanks
Scott

/********************************************************************************************************
 *                     INCLUDE FILES
********************************************************************************************************/

#include <cdcacm.h>
#include <usbhub.h>
#include "pgmstrings.h"
#include <SoftwareSerial.h>

/********************************************************************************************************
 *                    VARIABLES DEFINITION
********************************************************************************************************/

unsigned char Cmd;
unsigned char i;
String CrestronCmd;
String incomingString;
              
/********************************************************************************************************
 *                    FUNCTION PROTOTYPES
********************************************************************************************************/ 

// Satisfy the IDE, which needs to see the include statment in the ino too.
//#ifdef dobogusinclude
//#include <spi4teensy3.h>
//#include <SPI.h>
//#endif

SoftwareSerial myCrestron(15, 14); // RX, TX

class ACMAsyncOper : public CDCAsyncOper
{
public:
    uint8_t OnInit(ACM *pacm);
};

uint8_t ACMAsyncOper::OnInit(ACM *pacm)
{
    uint8_t rcode;
    // Set DTR = 1 RTS=1
    rcode = pacm->SetControlLineState(3);

    if (rcode)
    {
        ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
        return rcode;
    }

    LINE_CODING	lc;
    lc.dwDTERate	= 115200;
    lc.bCharFormat	= 0;
    lc.bParityType	= 0;
    lc.bDataBits	= 8;

    rcode = pacm->SetLineCoding(&lc);

    if (rcode)
        ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);

    return rcode;
}

USB     Usb;
//USBHub     Hub(&Usb);
ACMAsyncOper  AsyncOper;
ACM           Acm(&Usb, &AsyncOper);

/********************************************************************************************************
 *                    Setup - Do Once at Start of Program
 ********************************************************************************************************/ 

void setup()
{
 // Init Serial Port 
  Serial.begin( 115200 );
  myCrestron.begin(9600); // Start RS-232 Board
  myCrestron.println("Arduino RS-232 Port Ready:");

  incomingString = "";
  
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  Serial.println("Start");

  if (Usb.Init() == -1)
  
      Serial.println("OSCOKIRQ failed to assert");

  delay( 200 );

}

/********************************************************************************************************
 *                    Main Program Loop
 ********************************************************************************************************/ 

void loop()
{
 
 //***** Begin Crestron Code *****//
 
//Check if there's incoming serial data
  if (myCrestron.available() > 0) {
    //Read a byte from the serial buffer
    char incomingByte = (char)myCrestron.read();
    incomingString += incomingByte;

    //Checks for null termination of the string.
    if (incomingByte == '\0') {
    Serial.println (incomingString);
    incomingString = "";
    }
  } 

  
 //***** Begin Serial Monitor *****//
    Usb.Task();

    if( Acm.isReady()) {
       uint8_t rcode;

       /* reading the keyboard */
       if(Serial.available()) {
         uint8_t data= Serial.read();
         /* sending to the phone */
         rcode = Acm.SndData(1, &data);
         if (rcode)
            ErrorMessage<uint8_t>(PSTR("SndData"), rcode);
       }//if(Serial.available()...

       delay(50);

        /* reading the phone */
        /* buffer size must be greater or equal to max.packet size */
        /* it it set to 64 (largest possible max.packet size) here, can be tuned down
        for particular endpoint */
        uint8_t  buf[64];
        uint16_t rcvd = 64;
        rcode = Acm.RcvData(&rcvd, buf);
         if (rcode && rcode != hrNAK)
            ErrorMessage<uint8_t>(PSTR("Ret"), rcode);

            if( rcvd ) { //more than zero bytes received
              for(uint16_t i=0; i < rcvd; i++ ) {
                Serial.print((char)buf[i]); //printing on the screen
                myCrestron.print((char)buf[i]);
              }
            }
        delay(10);
    }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..

     //***** End Serial Monitor *****//
  
}
  1. Use hardware serial when available. There are 4 UARTs on the Mega and only 1 is used for bootload/serial console.

I cannot test this but I think this one line change will switch from software to hardware serial.

//SoftwareSerial myCrestron(15, 14); // RX, TX
#define myCrestron Serial3

  1. Move the read Crestron code inside the if (Acm.isReady() ) { ... }. Add the Acm.SndData line as shown below.
  //***** Begin Crestron Code *****//

  //Check if there's incoming serial data
  if (myCrestron.available() > 0) {
    //Read a byte from the serial buffer
    char incomingByte = (char)myCrestron.read();
    incomingString += incomingByte;

    //Checks for null termination of the string.
    if (incomingByte == '\0') {
      Serial.println (incomingString);
      Acm.SndData(incomingString.length(), incomingString.c_str());
      incomingString = "";
    }
  }
  1. A block diagram or schematic of how all the parts are connected would be useful.

  2. If all else fails, consider using a small, cheap linux system such as raspberry pi or orange pi for tasks like this. USB host support is much better.