Arduino > USB Host > RAZR Phone

Hello Guys. I’m working on a project to notify me, via text, of certain conditions at my home. I have been able to send text to the RAZR via the Aduino IDE Serial Monitor, using the sketch below. Of course, I would like the Arduino to send the messages autonomously. Another fellow has been working on the same project and has asked the same question to the author of the sketch. His response was to ‘Just replace strings that I send with strings you need to send.’ I assume this in reference to the line of code: rcode = Acm.SndData(1, &data);. I’ve tried different approaches such as filling the variable ‘data’ with characters, a sting, numeric values, etc. to no avail. Most of the time, the error references some code in the cdcacm library. The error is as follows:

acm_terminal.ino: In function ‘void loop()’:
acm_terminal:71: error: invalid conversion from ‘const char*’ to ‘uint8_t*’
acm_terminal:71: error: initializing argument 2 of ‘uint8_t ACM::SndData(uint16_t, uint8_t*)’

It seems to me it should be relatively easy to have the Arduino send text as is done via the serial monitor. Within an Arduino sketch, is it possible to emulate sending text entered via the serial monitor?

Thanks - Scotty

#include <cdcacm.h>
#include <usbhub.h>

#include "pgmstrings.h"

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

class ACMAsyncOper : public CDCAsyncOper
{
public:
    virtual 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);

void setup()
{
  Serial.begin( 115200 );
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
  Serial.println("Start");

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

  delay( 200 );
}

void loop()
{
    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
              }
            }
        delay(10);
    }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..
}
       if(Serial.available()) {
         uint8_t data= Serial.read();
         /* sending to the phone */
         rcode = Acm.SndData(1, &data);

This is sending the characters, in the guise of a uint8_t, one at a time.

If the first argument is the number of bytes to send, you could sent more than one using:

char mess[] = "Send me to the moon";
int len = strlen(mess);

rcode = Acm.SndData(len, (uint8_t *)mess);

If the first argument is not the number of bytes to send, you could still send them one at a time, in a for loop.

Thanks alot Paul. That helped

Thanks alot Paul. That helped a whole bunch.

Here’s the code:

#include <cdcacm.h>
#include <usbhub.h>

#include "pgmstrings.h"

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



class ACMAsyncOper : 
public CDCAsyncOper
{
public:
  virtual 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);

boolean done = false;
uint8_t rcode;
char mode[] = "AT+CMGF=1\r"; //used to put phone into text mode
int modelen = strlen(mode);
char phone[] = "AT+CMGW=16105551212\n>FROM RAZR\z";
int phonelen = strlen(phone);
char message[] = "From Razr!\r";
int messagelen = strlen(message);

void setup()
{
  Serial.begin( 115200 );
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
  Serial.println("Start");

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

void loop()
{
  Usb.Task();

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

    /* sending to the phone */
    if (done==false){//if true, prevents multiple messages from being sent

      Mode_Setup();
      delay(500);
      Read_Function();
      delay(500);
      Enter_Number();
      delay(1000);
      //Read_Function();
      //delay(500);
      //Send_Message();
      //delay(500);
      //Read_Function();
      //delay(500);  
    }
    if (rcode)
      ErrorMessage<uint8_t>(PSTR("SndData"), rcode);

    //Serial.println("            DATA SENT");
    done = true;
  }
  delay(50);

}//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..

int Mode_Setup(){
  for (int i = 0; i < modelen; i++){
    uint8_t data = mode[i];
    rcode = Acm.SndData(1, &data);
  }
  Serial.println("                         Mode Setup Complete");
}

int Enter_Number(){
  for (int i = 0; i < phonelen; i++){
    uint8_t data = phone[i];
    rcode = Acm.SndData(1, &data);
    delay(50);
  }
  Serial.println("                         Enter Number Complete");
}

int Send_Message(){
  for (int i = 0; i < messagelen; i++){
    uint8_t data = message[i];
    rcode = Acm.SndData(1, &data);
  }
  Serial.println("                         Send Message Complete");
}

int Read_Function(){
  /* 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 */
  Serial.println ("In Read Function");
  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
    }
  }
  delay(10);
}

I can now send commands to the phone. However, I’ve run into a little snag. The command I need to use is:
AT+CMGW=“phonenumber”\n

Type your message here.\z
Which sends a single SMS message.

(The message being embedded in char phone in the sketch. Now that I think of it, it makes sense that a number shouldn’t be dialed and then the message typed in. The number should be dialed after the message is typed.)

It won’t compile because of the \z. The error message is 'unknown escape sequence \z. I’ve tried adding the decimal value of 26, i.e. char phone = “AT+CMGW=16105551212\n>message”+26; in lieu of \z but I get a different error message about the size of ‘phone’.

I have been successful in calling another phone using ATD+12125551212; just to ensure I can dial out from the RAZR.

The following is displayed in the serial monitor when the sketch is executed:

Start
0705890300100A0705010200200007058202002000 Mode Setup Complete
In Read Function
AT+CMGF=1

OK
Enter Number Complete

Can anyone suggest a remedy?
Thanks - Scotty

It won't compile because of the \z. The error message is 'unknown escape sequence \z. I've tried adding the decimal value of 26, i.e. char phone[] = "AT+CMGW=16105551212\n>message"+26; in lieu of \z but I get a different error message about the size of 'phone'.

The message terminator is Ctrl-Z, not \z. You can not ADD a string and an int. The + operator is addition. It is NOT append. There is NO append operator.

Make the array have a fixed size. Do NOT have the compiler count the initializers. Assign the correct element of the array the value that corresponds with Ctrl-Z (26).