Go Down

Topic: Using Arduino to send texts and photos (Read 2 times) previous topic - next topic

gru491

I recently purchased a Circuits@home USB host shield to connect to a Motorola RAZR phone as outlined on Olegs website http://www.circuitsathome.com/mcu/programming/interfacing-arduino-to-a-cellular-phone/comment-page-1#comment-10520. It was pretty easy to follow along and I could get most of the AT Commands to work through the serial terminal as long as I was typing them in.
Ultimately I want to use different types of sensors to trigger SMS messages or send a photo. I am still pretty new I writing code and basically cannibalized other projects to make this code for when I press a button on pin 7 to tell the phone I am pressing the #1. When I press the button my serial terminal shows that the code functioned, but nothing happens with the phone. I am sure that if I get over this little hurdle I will be able to control the phone the way I want it.  

Code: [Select]
#include <avrpins.h>
#include <max3421e.h>
#include <usbhost.h>
#include <usb_ch9.h>
#include <Usb.h>
#include <usbhub.h>
#include <avr/pgmspace.h>
#include <address.h>

#include <cdcacm.h>

#include <printhex.h>
#include <message.h>
#include <hexdump.h>
#include <parsetools.h>

#include "pgmstrings.h"  

#define BUTTON 7// here is the button that I put in
int val =0;
int old_val = 0;
int state = 0;

char mobilenumber[] = "16195378604";

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 );
 Serial.println("Start");


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

void loop()
{
   Usb.Task();
 
   if( Usb.getUsbTaskState() == USB_STATE_RUNNING )
   {  
      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(buf[i]); //printing on the screen
             }              
           }
       delay(10);            
   }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..    

{ val = digitalRead(BUTTON);
 if ((val == HIGH) && (old_val == LOW))// This is the portion where it only runs
   {                                   // the sequence once
   state = 1;
   }
 else
   {
   state = 0;
   }
 if (state == 1) { Serial.println("AT+CKPD+''1''"); // To press the #1 button on the phone.
}
}
}



sbright33

#1
Nov 25, 2011, 03:36 pm Last Edit: Nov 25, 2011, 04:05 pm by sbright33 Reason: 1
Serial.println does not go to the phone.  I've been doing something similar, let me find the code...

Code: [Select]
uint8_t sndstr(char *s) {
uint8_t i,j,k;
for(i=0;s[i]!=0;i++) {
 k=s[i];
 j=Acm.SndData(1,&k); //could do all at once?
 if(j) return j;
}
i=13;
j=Acm.SndData(1,&i);
return j;
}

//later on...
sndstr("AT+MODE=2");


I have the Verizon RAZR.  
There are many differences that were difficult to overcome, but now it's working!

Which AT commands do you use to send a picture?  I'm interested!
If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

gru491

I am still a little confused where to put the AT commands in. Is the sndstr("AT+MODE=2"); portion where you are pushing it to the phone? Do you have a place earlier where you are defining the sndstr? The section of code you provided is where I was having trouble deciphering. What does AT+MODE do? I could not find it in the one reference I downloaded.

Through the tutorial on the Circuits@home site it shows how to get a return in the the terminal from each button you press on the phone. You can then use this command AT+CKPD="1" to press the #1. It was my  plan to have a trigger, in this case just a momentary switch to start a series of AT Commands with a short delay between them. I already mapped out what buttons to press as if I was doing it with my fingers to turn the camera on, take a photo and send it. Eventually I am going to use a hacked driveway motion sensor to trigger the camera and have it send me the photo. If I can get the code written right I might set it up so it takes 15 seconds of video and then sends it to me as long as there is movement triggering the sensor. I think there is a lot of really cool stuff that could be done with this. 

I am just stuck right now getting the commands from the Arduino to the phone when I press the button.

sbright33

When I call my sndstr function that is when it occurs.  You can send any AT command or any string.  Do not put this function call in a loop() which gets called 100x (acm_terminal sketch) unless that's what you want.  The particular AT command in my example is the first command I must send to my Verizon phone to initialize it to accept AT commands.  It is specific to Verizon not GSM.  You will not need to send it.  The sndstr function is defined before I call it. 

I understand what you are planning to do.  What specific sequence of keystrokes take a picture and send it?  Unfortunately I don't think the CKPD command is supported by my Verizon RAZR.  Will try it.  I hope it works with yours!  Have you tested it in terminal mode?  I recommend you try that first.  Knowing that it is possible to automate later with my code.
If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

sbright33

My project is somehow related, but I am not using the RAZR. 
I am using this camera mounted together with my Canon:
http://www.seeedstudio.com/depot/grove-serial-camera-p-945.html

Sending the image data with XBee.  Controlling a motorized panning head.  USB host to control Canon DSLR.
With a zoom lens I can zoom in to any part of the Lores image remotely.
Next step send the image object from the camera.
But it's really cool without that functionality!
If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

gru491

I like the serial camera you are looking at, I hope you get it up and running. I do have a Sparkfun GSM board, that would be cool to have that camera working with it.
You can get unlocked RAZRs on Ebay pretty cheap and I think you can get a prepard SIM card from T-Mobile for about $10.  The CKPD commands are GSM specific and I was able to go through the whole sequence of taking a photo and sending it by typing the commands into the serial terminal.
I should be able to get to using your code tomorrow and see where that takes me


sbright33

The serial camera works with Uno, but I am still developing the PTP image object code from Canon.  I got my RAZR on Ebay, but I needed Verizon because of the locations I plan to use it.  There is no T-Mobile coverage.  What keys are pressed?  I'm asking because I will have access to a GSM RAZR.  Did you find an AT command for each key?  Like the shutter button?
If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

gru491

I tried your code out and it took me a little while to get it to compile. I was not able to get it to work, I know it must be something really simple that I am missing. What is weird is that I have full functionality of the phone as long as it is hooked to my computer and when I press my button it will print out what ever I want it to say. How do I actually sent the commands to the phone?

As for the button sequence this is how I figured it out. Go to http://www.circuitsathome.com/mcu/programming/interfacing-arduino-to-a-cellular-phone follow the AT commands on the page. AT+CMER=3,1,0,0,0 will give you the name of the key you press like +CKEV: "1",1
+CKEV: "1",0. The character in the " " is the name of the key and this AT+CKPD="1" when sent through the terminal will be as if you pressed it. Just take and write down the keys needed to send a photo or video and put them in the sketch, I am sure that you will have to work on some delay times to make it run smoothly.

sbright33

I am not familiar with the RAZR as a phone user.  Forgot programming and Arduino for a second.
What keys do you press, as a phone user, to send a picture?
If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

deroses


Serial.println does not go to the phone.  I've been doing something similar, let me find the code...

Code: [Select]
uint8_t sndstr(char *s) {
uint8_t i,j,k;
for(i=0;s[i]!=0;i++) {
 k=s[i];
 j=Acm.SndData(1,&k); //could do all at once?
 if(j) return j;
}
i=13;
j=Acm.SndData(1,&i);
return j;
}

//later on...
sndstr("AT+MODE=2");


I have the Verizon RAZR.  
There are many differences that were difficult to overcome, but now it's working!

Which AT commands do you use to send a picture?  I'm interested!


this is exactly what i was looking for to bridge the gap from oleg to sending AT commands - thanks!!! my only question, if i could - how do you send cltr-z or "" type commands using your sndstr format (to send AT+CGMS type things)?  is there some way to send ascii 34 or similar?  i get conversion errors - but i am not a good arduino programmer.  thanks again!

sbright33

You can do it in text mode.  See sndmsg().  I have not looked at this for awhile, but it works with my phone.

Code: [Select]

#include <avrpins.h>
#include <max3421e.h>
#include <usbhost.h>
#include <usb_ch9.h>
#include <Usb.h>
#include <usbhub.h>
#include <avr/pgmspace.h>
#include <address.h>
#include <cdcacm.h>
#include <printhex.h>
#include <message.h>
#include <hexdump.h>
#include <parsetools.h>
#include "pgmstrings.h" 

#define IF0 if(0){
#define NDREC rcvd=64;rcode=Acm.RcvData(&rcvd,buf);
#define DELREC delay(2000);NDREC
#define DELREC1 delay(500);NDREC
#define PBUF for(i=0;i<rcvd;i++)Serial.print(buf[i]);
#define PRCV Serial.print(rcvd);
#define PHLIGHT sndstr("ATD611");delay(500);sndstr("/r");
#define CALLHU(num) sndstr(num);delay(15000);sndstr("/rATH");DELREC1;DELREC;
#define P32 Serial.write(32);
#define P13 Serial.write(13);

int first=1;
int j,svc,rss,hr,mi,se;
long k;
uint8_t  rcode,buf[64];           
uint16_t rcvd=64,i;
String s="1234567890123456789012345678901234567890123456789012345678901234"; //64
char t[12]="AT+CMSS=nn";
char cmgr[12]="AT+CMGR=nn";
char mnum[3]="nn";

int pirPin = 3;
int pirVal;

void(* resetFunc)(void)=0; //declare reset function @ address 0
class ACMAsyncOper : public CDCAsyncOper {
public: virtual uint8_t OnInit(ACM *pacm);
};
uint8_t ACMAsyncOper::OnInit(ACM *pacm) {
    uint8_t rcode;
    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;
ACMAsyncOper  AsyncOper;
ACM           Acm(&Usb, &AsyncOper);

void setup(){
  Serial.begin( 115200 );
  if (Usb.Init() == -1)
      Serial.println("OSCOKIRQ failed to assert");     
  delay( 200 );
  pinMode(pirPin,INPUT);
  //pinMode(13,OUTPUT);
  digitalWrite(pirPin,HIGH);  //instead 10k pullup but not enough
}
uint8_t sndstr(char *s) {
uint8_t i,j,k;
for(i=0;s[i]!=0;i++) {
  k=s[i];
  j=Acm.SndData(1,&k); //could do all at once?
  if(j) return j;
}
i=13;
Acm.SndData(1,&i);
return j;
}
uint8_t sndnocr(char *s) {
uint8_t i,j,k;
for(i=0;s[i]!=0;i++) {
  k=s[i];
  j=Acm.SndData(1,&k);
  if(j) return j;
}
i=13;
//Acm.SndData(1,&i); only difference from above
return j;
}
uint8_t sndmsg(char *n, char *msg) {
uint8_t i;
sndnocr("AT+CMGW=");  //CMGW or S when online, doesn't work ERROR
i=34; Acm.SndData(1,&i);  //"
sndnocr(n);
i=34; Acm.SndData(1,&i);
i=13; Acm.SndData(1,&i);
sndnocr(msg);
i=26; Acm.SndData(1,&i);
DELREC1 DELREC
//t="AT+CMSS=nn"; already init above/below
t[8]=buf[9];
t[9]=buf[10];
if(t[9]==13) t[9]=0; //single digit
//Serial.print  (int(t[8]));
//Serial.println(int(t[9]));
//Serial.println(t);
sndstr(t); //comment this for testing
//no return yet
}
void waitsvc(int d) {
svc=0;
for(j=0;svc==0;j++) { //j<100 should be svc==0 for/while no service signal ==1 skips
//buf[11]=48;
//NDREC  //flush from PHLIGHT below
sndstr("AT+CIND?");  //only works 1x w/svc OK now!
DELREC
svc=buf[11]-48; rss=buf[17]-48;
//Serial.print(svc); Serial.print(rss);
//if(svc==1) {PHLIGHT} //does not need immediate DELREC like above ATE0?
delay(d*1000);
} //for svc==0
NDREC
}
void waitSMS() {
rcvd=6;
while(rcvd==6) {  //CRLFokCRLF
  sndstr("AT+CMGL=\"REC UNREAD\"");  //READ to test UNREAD when ready
  DELREC1 PRCV PBUF P32
  while(rcvd==0) {DELREC1 PRCV PBUF P32}
  }
//if(rcvd!=6)
sndstr("/r"); //stops much data
for(i=0;i<rcvd;i++)  s.setCharAt(i,buf[i]);  //starts with 0!
for(i=rcvd;i<64;i++) s.setCharAt(i,0);  //clear the rest
//Serial.println(s);   
//if(s.indexOf("curb")>0) Serial.println("Found");  //-1 is not found
cmgr[8]=mnum[0]=buf[9];
cmgr[9]=mnum[1]=buf[10]; //could be 13 CR single digit fix later
mnum[2]=0;
P13
for(k=0;k<12;k++) {DELREC1 PRCV P32}
P13
}
void loop()
{   Usb.Task(); 
if( Usb.getUsbTaskState() == USB_STATE_RUNNING){ 
  if(first==1) {
     first=0;
//IF0 allows to keep formatting/colors in code
//IF0
     sndstr("AT+MODE=2");
     sndstr("ATE0");
     DELREC //needed or will crash! check for this error everywhere
//}
//delay(5000);
//PHLIGHT DELREC  //to make sure its running in field
//waitsvc(15);
//waitSMS();
//if(s.indexOf("CMGLnot")>0)  //if pw not found crashes without sending, +CMGL always
//k is long int
pirVal=HIGH;
for(j=0,k=1;pirVal==HIGH;k++){ //no movement
  pirVal=digitalRead(pirPin);
  if(pirVal==LOW){j++;delay(2000);}
  if(j<4)pirVal=HIGH;
  if(k%(20*60*5)==0)j=0; //every 5 mins overflow 30min? No k is long now
  if(k%(20*60*30)==0)break; //test every 30 min
  delay(50); //1/20 sec
  }
CALLHU("ATD9785443562")
DELREC;
DELREC; //req?
//sndmsg("2626969619","Hello Beaver"); //still in buffer
for(j=0;j<5*60;j++)delay(1000); //5min
resetFunc();  //call reset does not initialize registers

IF0
    sndstr("AT+CBC");
    DELREC Serial.println(buf[10]); //'1'=49?=100% battery or 7 or 9 is 90%
    sndstr("AT+CCLK?");
    DELREC
    hr=(int(buf[19])-48)*10+buf[20]-48;
    mi=(int(buf[22])-48)*10+buf[23]-48;
    se=(int(buf[25])-48)*10+buf[26]-48;
    Serial.print(hr); Serial.print(':');
    Serial.print(mi); Serial.print(':');
    Serial.print(se);
    while(rcvd!=8) {DELREC1 PRCV PBUF}
    //probably RING?
    //cmgr[8]=mnum[0]; cmgr[9]=mnum[1]; already done in waitSMS()
    //sndstr(cmgr); //gets timestamp too for specific SMS, no other purpose
} //IF0
} //first=1
//modified from ACM terminal:
  if(Serial.available()) {
    uint8_t data= Serial.read();
    rcode = Acm.SndData(1, &data);
    if (rcode)ErrorMessage<uint8_t>(PSTR("SndData"), rcode); }
  delay(50);
  rcvd=64;
  rcode = Acm.RcvData(&rcvd, buf);
  if(rcode && rcode != hrNAK) ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
  if( rcvd ) { //more than zero bytes received
  //modified by me:
  Serial.println();
  Serial.print("Size: ");
  Serial.println(rcvd);
    for(uint16_t i=0; i < rcvd; i++ ) {
     j=buf[i];
     if(j==13) {
        Serial.write(13);
        //Serial.write(10);
        //i+=3;  //for single line results
        }
     if((j!=13)&&(j!=10)) {
        Serial.print(buf[i]); //printing on the screen
        Serial.print(" "); Serial.print(i); Serial.print(" "); Serial.println(j);
        }
     }
  }
  delay(10);           
  } //USB_STATE_RUNNING top of loop()
} //loop()
If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

DWP2

Could somebody please specify the code that does the sending of the photo (no problems with the SMS)?

I've been searching the net for some time now but have been unsuccessful finding that final piece for my project. Thanks much!

Go Up