极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 29753|回复: 36

基于SIM900A的智能家居之----远程完全控制电脑

[复制链接]
发表于 2013-9-22 00:38:12 | 显示全部楼层 |阅读模式
  SIM900A,集成GSM和GPRS功能,可是鲜见玩GPRS 的,论坛里也没有多少用900a的朋友,早想远程控制家电,觉得论便携移动还有成本来说,900a比ENC28J60和W5100有优势,当然实时数据传输还得后者,所以小弟斗胆献丑,扒一扒SIM900a的事儿。
  上个月我把家里路由器的9v电源插到SIM900A上让电流倒灌到uno中烧了板子和1602,后来用万用表测电压,着实被吓了一跳,明明是直流电但是电压高一下低一下,我勒个去,还是PWM的电压?!
  后来买了mega2560,没有了uno程序到19kb就烧录不了(可能是变量太多?)的问题,这次写智能家居也差不多这么大,完全没问题,可是为什么uno上能播放的SD卡音乐mega却识别不了??
  进入正题,先前装了网灵客户端,可以用手机或者电脑访问控制另一台电脑,晚上手机AP上网不用下床就能关了电脑,远程调文件什么的so easy,当然用GPRS流量访问的话一个电脑截屏300多kb,您自己斟酌着用。这么好的软件(俺还不是付费升级用户)唯一不能做的,就是开电脑了,咱不能为了以防万一需要电脑文件就24小时开着PC吧。睡眠休眠?不好意思,那样的话会自动断网,断网了的话当然控制不了电脑了。所以,我的智能家居第一步,控制电脑开机(关机什么的就用网灵)。
  所用配件:
           Arduino什么板都可以,本人2560,60元;
           SIM900A 模块,142元;
           USBtinyISP(这个因为我不小心下程序时没拔连900a的串口线,不知道烧了什么,后来bootloader也烧不上,万幸用编程器下载程序能用,就是每次下载完了拔掉线插mega麻烦),35元;
           舵机,耳麦,红外遥控器和接收头,三色RGB灯,蜂鸣器;
           木板,钉子,锯子等,反正您看着什么合适能成就用吧;


连线的话根据自己的板子在代码开头相应位置改,就不说了,上代码(I2C什么的被我烧了,有的可以连上,没有的不管也可):
int ledpin=13;     //定义数字接口13
int val;           //定义变量val
#include<LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
#include<Wire.h>
#include <Servo.h>
Servo myservo;
#define MAXCHAR 81 //recive buff max char,81 orginally

#include<IRremote.h>
int RECV_PIN = 5;
IRrecv irrecv(RECV_PIN);
decode_results results;

int buzzer=53;
int redpin=A9;
int bluepin=A10;
int greenpin=A8;

//#include "Raw.h"
//#include "Message.h"
char aa[MAXCHAR];  //recive gsm model back signal,接收GSM的返回信号GSM》》Atmega
int j=0;           //recive index   
int g_timeout=0;   //handing time
int k=0;           //sms content identifier
int l=0;           //sms send to number identifier
int m=0;           //call identifier
//boolean flag2=0;
//unsigned long time;
boolean flag=0;
boolean flag1=0;
////////////////////////////////////////////////////
char ATE0[]="ATE0";
char CREG_CMD[]="AT+CREG?";////////////网络注册信息
char SMS_send[]="AT+CMGS=18";//////////发送短消息
char ATCN[]="AT+CNMI=2,1";///////////////新消息指示
char CMGF0[]="AT+CMGF=0";//////////////设置短消息的发送格式PDU
char CMGF1[]="AT+CMGF=1";//////////////纯文本
char CMGR[12]="AT+CMGR=1";////////////读取短消息
char CMGD[12]="AT+CMGD=1";////////////删除所有已读短消息
///////////////////////////////////////////////////
#define SEND_MESSA_TO_YOUR "at+cmgs=\"159********\"\r\n"    //l=0
#define SEND_MESSA_TO_YOUR_1 "at+cmgs=\"182********\"\r\n"  //l=1

#define SEND_MESSA_CONTENT "From SIM900A"                   //k=0
#define SEND_MESSA_CONTENT_1 "Master,servo moved done"      //k=1

#define CALL_YOU_TELNUMBER "ATD159********;\r\n"            //m=0
#define CALL_YOU_TELNUMBER_1 "ATD182********;\r\n"          //m=1
///////////////////////////////////////////////////

/*
  Read input serial
*/
int readSerial(char result[])///////////////////////////////////SIM900a to Arduino
{
  int i = 0;
  while (Serial.available() > 0)  //返回串口缓冲区字符个数 已经传输到,并存储在串行接收缓冲区(能够存储64个字节)的字节数(字符)。
  {
    char inChar = Serial.read();
    if (inChar == '\n')////////////////换行,一次只能读一行
    {
      result = '\0';///////////////string end
      Serial.flush();/////////////////一次发送串口接收缓冲器中存储的数据(ATD159*******)
      return 0;//////////////////////if中的跳出用法
    }
    if(inChar!='\r')
    {
      result = inChar;
      i++;
    }
  }
}

/*
  clean buff
*/
void clearBuff(void)
{
  for(j=0;j<MAXCHAR;j++)
  {
    aa[j]=0x00;
  }
  j=0;
}

/*
  clean buff
*/
int Hand(char *s)
{
  delay(200);
  clearBuff();
  delay(300);
  readSerial(aa);//////////////////////////aa[]=result[]
  if(strstr(aa,s)!=NULL)             //检测单片机和模块的连接,aa中若有s字符 串
  {
    g_timeout=0;
    clearBuff();
    return 1;
  }
  if(g_timeout>50)
  {
    g_timeout=0;
    return -1;
  }
  g_timeout++;////////////////半秒加一
  return 0;
}


/*
  13 LED test
*/
void led(int i)
{
  if(i)
  {
    digitalWrite(ledpin,HIGH);//点亮数字13 口LED。
    delay(500);
  }
  else
  {
    digitalWrite(ledpin,LOW);//熄灭数字13 口LED
    delay(500);
  }
}

void AT(void)
{
  clearBuff();
  Serial.println(ATE0);////////////
  delay(100);
  readSerial(aa);

  while(strstr(aa,"OK")==NULL)//////////OK在aa中第一次出现的位置,如果没有则返回NULL
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("connect [..]");

    clearBuff();
    led(1);
    Serial.println(ATE0);
    delay(500);
    readSerial(aa);
    led(0);
  }

    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" connected");

  clearBuff();
  Serial.println(ATCN);
  delay(500);
  while(Hand("OK")==0);//////////////////aa中第二次出现OK字符串
  
  clearBuff();
  Serial.println("AT+CLCC");
  delay(500);
  while(Hand("OK")==0);                 //laidianxianshi phone number
  clearBuff();
  Serial.println("AT+CLIP=1\r\n");
  delay(500);
  while(Hand("OK")==0);//////////////////aa中第二次出现OK字符串
  
  while(1)
  {
    clearBuff();
    Serial.println(CREG_CMD);          //AT+CREG?
    delay(500);
    readSerial(aa);

    if((strstr(aa,"0,1")!=NULL)||(strstr(aa,"0,5")!=NULL))/////////出现0,1或0,5了的话……
    {
      clearBuff();
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(" register [OK]");
      Serial.println("OK");
      break;//////////////////////跳出while(1)
    }
    else
    {
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(" register [..]");
      delay(500);
    }
  }
}


void send_english(int l,int k)
{
  clearBuff();
  Serial.println(CMGF1);/////////设置发送格式为文本
  delay(200);                 //not necessary as hand() delay 0.5s
  while(Hand("OK")==0);////////aa中没有OK字符串就先在此等待;
  
  clearBuff();
  switch(l){
    case 0:
         Serial.println(SEND_MESSA_TO_YOUR);
         break;
    case 1:
         Serial.println(SEND_MESSA_TO_YOUR_1);
         break;
  }
  delay(200);
  while(Hand(">")==0);/*在接收电话号码与短信内容之间的必填字符,we can't use delay() here,cause??????????
  function Hand() invoking readSerial(aa),and ">" will be transmitted immediately,once we missed ">",aa can not got it one more time*/
switch(k){
case 0:
  clearBuff();
  Serial.println(SEND_MESSA_CONTENT);  //发短信内容
  break;
case 1:
  clearBuff();
  Serial.println(SEND_MESSA_CONTENT_1);  //发短信内容
  break;
}  
  while(Hand(">")==0);
  delay(100);                 //not necessary
  Serial.print("\x1A");      //发送结束符号,\x means hex
  delay(10);

  delay(1000);                //real sending sms time
  while(Hand("OK")==0);
}



void send_call(int m)
{
  clearBuff();
  switch(m){
    case 0:
         Serial.println(CALL_YOU_TELNUMBER); //打电话
         break;
    case 1:
         Serial.println(CALL_YOU_TELNUMBER_1); //打电话
         break;
  }
  delay(2000);
  while(Hand("OK")==0);
}

void color (unsigned char red, unsigned char green, unsigned char blue)
  {   
          analogWrite(redpin, 255-red);   
          analogWrite(bluepin, 255-blue);
          analogWrite(greenpin, 255-green);
  }

void setup (void) {
  pinMode(buzzer,OUTPUT);
  pinMode(redpin, OUTPUT);
  pinMode(greenpin, OUTPUT);  
  pinMode(bluepin, OUTPUT);
  myservo.attach(9);
  myservo.write(90);

  lcd.init(); // initialize the lcd
  lcd.backlight();
  Serial.begin(9600);//设置波特率为9600
  pinMode(ledpin,OUTPUT);//设置数字13 口为输出接
  irrecv.enableIRIn();          //启动红外解码
  Serial.println("serial port [ok]!");//显示字符串
}

void loop (void) {
  int aa13,aa12,y;  //index,index1;
  char sms[5],cmgr[13];
  boolean flag_read=0;
  //String comdata="";
  //char subaa[5];
  //String aaa;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Welcome To");
  lcd.setCursor(0,1); // 定义光标位置为第二行第二个位置
  delay(10);
  lcd.print("www.csgsm.com");
  delay(100);
  color(255,0,255);         //待机中,绿色
  digitalWrite(buzzer,LOW);
  AT();
  myservo.write(100);
  clearBuff();              //删除则报错
while(1)
{  
   while(Serial.available()>0)
   {
     delay(50);        //'L'型读写串行数据缓冲器
     readSerial(aa);
     if(strstr(aa,"RING")!=NULL)               //call in
       {
       Serial.println(aa);
       lcd.print("got a call from:");
       Serial.println("RING,Answer?");        //set buzzer on,which modulated by pulse wave
       flag=1;                                 //zhi jie ting biao zhi
       Serial.flush();                        //
       clearBuff();
       color(0,255,255);                       //来电话,红色
       while(!(irrecv.decode(&results)))
       {
       digitalWrite(buzzer,HIGH);
       delay(300);
       digitalWrite(buzzer,LOW);
       delay(400);
       }
      
       }
      if(strstr(aa,"+CMTI: \"SM\","))            //if we got a message
      {
        color(255,255,0);    //blue
        aa13=aa[13];
        aa12=aa[12];
        y=(aa12-48)*10+(aa13-48);
        lcd.clear();
        lcd.print(aa);
        Serial.print("Read message ");
        /*Serial.print(aa[0]);          //+
        Serial.print(aa[10]);         //"
        Serial.print(aa[11]);         //,
        Serial.print(aa[12]);         //3
        Serial.print(aa[13]);         //4
        Serial.print(aa[14]);         //
        Serial.print(aa[15]); */
        Serial.print(y);
        Serial.println("?");
        Serial.println(aa);
        flag1=1;      //got a sms
        flag_read=0;  //haven't read yet
           cmgr[0]='A';
           cmgr[1]='T';
           cmgr[2]='+';
           cmgr[3]='C';
           cmgr[4]='M';
           cmgr[5]='G';
           cmgr[6]='R';
           cmgr[7]='=';
           cmgr[8]=aa[12];
           cmgr[9]=aa[13];
           cmgr[10]='\r';
           cmgr[11]='\n';
           cmgr[12]='\0';
           Serial.flush();  //if we don't clear now,this serial.available check would run all the time and occupy too much ir's check time
      }
   }                                              //while(Serial.available) end
   if (irrecv.decode(&results))
   {
    switch(results.value)
    {
     case 0xFF22DD:
          color(0,0,0);
          AT();                     //initialization
          color(255,0,255);             //white light
          break;
     case 0xFF30CF:                 //"1",发短信
          lcd.clear();              // 屏幕清空,光标位置归零
          lcd.setCursor(0,0);
          lcd.print(" send sms [..]");
          k=0;
          send_english(l,k);        //k
          break;
     case 0xFF18E7:                 //"2",发短信
          lcd.clear();              // 屏幕清空,光标位置归零
          lcd.setCursor(0,0);
          lcd.print(" send sms [..]");
          k=1;
          l=0;
          send_english(l,k);      
          break;
      case 0xFF42BD:                  //"7"call out
           lcd.clear(); // 屏幕清空,光标位置归零
           lcd.setCursor(1,1);// 定义光标位置为第二行第二个位置
           lcd.print(CALL_YOU_TELNUMBER);
           delay(10);
           lcd.setCursor(1,0);
           delay(10);
           m=0;
           color(0,255,255);
           send_call(m);
           delay(5000);
      case 0xFF52AD:                    //"9"answer call in
           if(flag)
           {
           color(255,255,0);
           for(int w=0;w<50;w++)
           {
           digitalWrite(buzzer,HIGH);
           delay(5);
           digitalWrite(buzzer,LOW);
           delay(5);
           }
           digitalWrite(buzzer,LOW);
           Serial.println("ATA\r\n");
           }
           break;
      case 0xFFA25D:                      //"ON/OFF" hang up
           Serial.println("ATH\r\n");
           color(255,0,255);
           break;
      case 0xFFB04F:                     //press U\SD button,read SMS again;at the first time we read automatically
           clearBuff();
           Serial.flush();
           color(255,0,255);
           Serial.print(cmgr);
           delay(200);
           readSerial(aa);           //读出第一行,带走换行符,下一个a
           while(strstr(aa,"+CMGR:")==NULL)
           {
             clearBuff();
             delay(400);
             readSerial(aa);
           }
           Serial.println(aa);
           
           Serial.println("Receive SMS from:");
           if(flag_read==0)
           {
           for(int i=24;i<35;i++)
           {
             Serial.print(aa);
           }
           }
           else
           {
             for(int i=22;i<33;i++)
             {
             Serial.print(aa);
             }
           }
           flag_read=1;
           
           Serial.print("\r\n");        //0x0D其十进制ASCII码为13.第二次读短信read变unread,号码位置有所变动
           Serial.println("Remaining room of serial buffer:");
           Serial.println(Serial.available()); //aa接收完了串口缓冲器里的数据,读一个少一个,最后没了为0
           for(int j=0;j<5;j++)
           {
             sms[j]=char (Serial.read());
           }
           Serial.print(sms);
           
           switch(sms[0])
           {
           case 0x61:
                  myservo.write(110);    //110 middle,90 up
                  delay(400);
                  break;
            default:break;
           }
           
           clearBuff();
           Serial.flush();
           color(255,0,255);
           break;
    }                                    //switch over
    irrecv.resume();
  } //if(IR.available) over
    if(flag1==1)
    {
           clearBuff();
           Serial.flush();
           color(255,255,0);
           Serial.println(cmgr);
           delay(200);
           readSerial(aa);           //读出第一行,带走换行符,下一个b
           while(strstr(aa,"+CMGR:")==NULL)
           {
             clearBuff();
             delay(400);
             readSerial(aa);
           }
           Serial.println("move servo");
           Serial.println(aa);
           clearBuff();
           for(int j=0;j<5;j++)
           {
             sms[j]=char (Serial.read());
           }
           Serial.println(sms);
           switch(sms[0])
           {
           case 0x62:
                myservo.write(120);
                delay(2500);
                myservo.write(80);
                //send_english(1,1);
                delay(1000);
                break;
           }
           color(255,0,255);
           flag1=0;
           flag_read=1;
    }//if(flag1)end
  }//while(1) never end
} //loop end
注意由于读取短信的AT指令长于64字节,要把串口缓冲区改到128字节,这个在吧里搜(先前一直怕引起其他麻烦没用,后来实验效果很好)。
  目前功能,正常的拨打电话,接听电话,读取短信(产生控制舵机命令),发送某内容短信给某电话。读取短信时是首先Arduino自己读一遍,是某个命令(这里收到“b”就让舵机工作)就执行指定的操作,不是不执行,这是远程控制操作,而后遥控器按键可以再次读取这条短信,即使是已读的(可以改改液晶显示放在客厅当座机用)。
  接下来扒一扒本屌自制的舵机驱动的开电脑开关,手头只有木头钉子,什么乐高积木、机械之类的东西一概没有。制成才发现木头确实是最适合的材料。图见““C”形舵机架”。
  三块木板钉一起成“C”形,舵机用螺丝、钢针固定,用粗铁丝或钢丝折成“L"形,小拐弯处用于插入舵机头。铁丝另一端插入一根小木头(我用的筷子^_^...),木头下端穿过固定在木板上的瓶盖,最后将铁丝和舵机柄上的小孔捆绑起来。舵机转到100居中,转到120时木头向下顶住笔记本电源键。

  最后说SIM900A的事儿,没有的童鞋绕道吧,都是些繁琐的细节问题。
  一、串口调试方法(先用GSM串口调试工具玩熟练,把该记的指令记下)
1.短接跳线帽不要
2.插SIM卡,RS232线连好,电源接上等到由0.8s闪烁一次变为3s闪烁一次时打开串口调试助手
3.COM口不要大于5,越小越好
4.Arduino和电脑间有串行数据缓冲器,但是与SIM900a间没有?
5.打电话测试ATD13399059548;分号必须
6.接电话 AT+CLIP=1来电显示,ATA接听,ATH挂机
7.开机加电源后等几秒再开串口调试器
8.持续CREG不返回OK时试试重启或按reset
9.持续ATE0?串口调试工具没有关闭并安全退出,重新打开并关闭退出,或等模块灯3s闪两次后再开IDE串口
即-下程序,拔USB,开服务器,插USB,等3s灯,开串口
10.while();{}中的“;”编译器检测不出来,复制代码时注意
11.使用USBtinyISP下载程序时先连ISP到电脑,再连到mega,下载程序需要1分钟,红线靠Uart口.十根线不能拔
12.多次发送AT指令并检测返回信号提高接收率且最主要能接收几行readSerial(aa)遇换行跳出

  一个小问题,执行程序时舵机不停地响动,貌似是检测位置,不知道如何解决,有经验的请留步。
SIM900A调试起来不像吧里其他GSM模块,没有库函数,只能发送接收AT指令,问题很多,欢迎交流。

全套配件

全套配件

“C”形舵机架

“C”形舵机架

舵机按笔记本电源键

舵机按笔记本电源键
回复

使用道具 举报

发表于 2013-9-22 12:14:15 | 显示全部楼层
我有个SIM900A,一直放着。多谢分享!
回复 支持 反对

使用道具 举报

发表于 2013-9-27 22:16:11 | 显示全部楼层
原来你的是笔记本电脑,用陀机控制。我做的是台式办公电脑的远程开机,直接加个继电器并接至电脑的电源开关,需要的时候发脉冲模拟电源开关动作电脑就启动了,也就是继电器合上150ms后断开就可以了。我的代码很简单哦!你都已经把串口缓冲区改到128字节了,直接使用String函数就可以了。我在TC35i,sim900A,GTB900B等几个模块上都调试通过了!

程序与GTM900通信正常,接收短信正常,可以控制继电器。完全能判断是不是我的手机号发的短信,短信内容也能判断,必须是我的手机号发的正确的短信内容,继电器才会动作。否则只是指示灯闪烁6次。添加了断电又上电后的判断,因为模块上电后就会向单片机发送AT-Command Interpreter ready命令,程序判断收到关键词“Interpreter”或者短信收到“Interpreter”,整个模块(等待30秒,给模块找网络的时间,单片机就向模块发AT指令初始化)就重新初始化。
String comdate="";
String s1="+CMT:";
String s2="861388XXXXXXX";
String s3="QDDN2013QC";
String s4="Interpreter";


while(Serial.available()>0)
{
  comdate+=char(Serial.read());
   delay(10);
}

if(comdate.length()>0)
{
if(comdate.indexOf(s1)!=-1&&comdate.indexOf(s2)!=-1&&comdate.indexOf(s3)!=-1)
  {
    digitalWrite(8,HIGH);
      delay(150);
      digitalWrite(8,LOW);
       delay(50);
        
       digitalWrite(13,HIGH);
      delay(1000);
      digitalWrite(13,LOW);
       delay(50);
  comdate=String("");
  Serial.println("AT+CMGD=1,4");
      
}



回复 支持 反对

使用道具 举报

发表于 2013-9-27 22:19:43 | 显示全部楼层
自己用AT命令很灵活啊,官网的库函数换模块的时候就要去修改库函数了哦!
我都是自己写:
delay(3500);
pinMode(8,OUTPUT);
pinMode(13,OUTPUT);
Serial.begin(9600);
delay(100);
Serial.println("AT");
delay(350);
Serial.println("ATE0");
delay(350);
Serial.println("AT+CMGF=1");
delay(350);
Serial.println("AT+CNMI=2,2");
delay(350);
Serial.println("AT&W");
delay(350);
Serial.println("AT+CMGD=1,4");
delay(350);
comdate=String("");
回复 支持 反对

使用道具 举报

发表于 2013-9-27 22:24:20 | 显示全部楼层
你的代码太像 创思通信的示例代码了!我不太会用指针,也不喜欢用哦!所有自己写了自己的代码!
回复 支持 反对

使用道具 举报

发表于 2013-9-27 22:25:53 | 显示全部楼层
下面是创思通信的代码:
int DI = 12;
int RW = 11;
int DB[] = {
  3, 4, 5, 6, 7, 8, 9, 10};//使用数组来定义总线需要的管脚
int Enable = 2;
int ledpin=13;     //定义数字接口13
int val;           //定义变量val
#define MAXCHAR 81 //recive buff max char
char aa[MAXCHAR];  //recive gsm model back signal
int j=0;           //recive index
int g_timeout=0;   //handing time
////////////////////////////////////////////////////
char ATE0[]="ATE0";
char CREG_CMD[]="AT+CREG?";
char SMS_send[]="AT+CMGS=18";
char ATCN[]="AT+CNMI=2,1";
char CMGF0[]="AT+CMGF=0";
char CMGF1[]="AT+CMGF=1";
char CMGR[12]="AT+CMGR=1";
char CMGD[12]="AT+CMGD=1";
///////////////////////////////////////////////////
#define SEND_MESSA_TO_YOUR "at+cmgs=\"18622944083\"\r\n"    //填入你手上的手机号码 不是板子的
#define SEND_MESSA_CONTENT "tpytongxin.taobao.com"
#define CALL_YOU_TELNUMBER "ATD18622944083;\r\n"    //填入你手上的手机号码 不是板子的
///////////////////////////////////////////////////
void LcdCommandWrite(int value) {
  // 定义所有引脚
  int i = 0;
  for (i=DB[0]; i <= DI; i++) //总线赋值
  {
    digitalWrite(i,value & 01);//因为1602液晶信号识别是D7-D0(不是D0-D7),这里是用来反转信号。
    value >>= 1;
  }
  digitalWrite(Enable,LOW);
  delayMicroseconds(1);
  digitalWrite(Enable,HIGH);
  delayMicroseconds(1); // 延时1ms
  digitalWrite(Enable,LOW);
  delayMicroseconds(1); // 延时1ms
}
void LcdDataWrite(int value) {
  // 定义所有引脚
  int i = 0;
  digitalWrite(DI, HIGH);
  digitalWrite(RW, LOW);
  for (i=DB[0]; i <= DB[7]; i++) {
    digitalWrite(i,value & 01);
    value >>= 1;
  }
  digitalWrite(Enable,LOW);
  delayMicroseconds(1);
  digitalWrite(Enable,HIGH);
  delayMicroseconds(1);
  digitalWrite(Enable,LOW);
  delayMicroseconds(1); // 延时1ms
}

/*
  Read input serial
*/
int readSerial(char result[])
{
  int i = 0;
  while (Serial.available() > 0)
  {
    char inChar = Serial.read();
    if (inChar == '\n')
    {
      result[i] = '\0';
      Serial.flush();
      return 0;
    }
    if(inChar!='\r')
    {
      result[i] = inChar;
      i++;
    }
  }
}

/*
  clean buff
*/
void clearBuff(void)
{
  for(j=0;j   {
    aa[j]=0x00;
  }
  j=0;
}

/*
  clean buff
*/
int Hand(char *s)
{
  delay(200);
  clearBuff();
  delay(300);
  readSerial(aa);
  if(strstr(aa,s)!=NULL)             //检测单片机和模块的连接
  {
    g_timeout=0;
    clearBuff();
    return 1;
  }
  if(g_timeout>50)
  {
    g_timeout=0;
    return -1;
  }
  g_timeout++;
  return 0;
}

/*
  lcd 1602 string
*/
void lcd(char *str)
{
  while(*str!='\0')
  {
    LcdDataWrite(*str);
    delay(2);
    str++;
  }
}

/*
  13 LED test
*/
void led(int i)
{
  if(i)
  {
    digitalWrite(ledpin,HIGH);//点亮数字13 口LED。
    delay(500);
  }
  else
  {
    digitalWrite(ledpin,LOW);//熄灭数字13 口LED
    delay(500);
  }
}

void AT(void)
{
  clearBuff();
  Serial.println(ATE0);
  delay(500);
  readSerial(aa);

  while(strstr(aa,"OK")==NULL)
  {
    LcdCommandWrite(0x01); // 屏幕清空,光标位置归零
    lcd(" connect [..]");

    clearBuff();
    led(1);
    Serial.println(ATE0);
    delay(500);
    readSerial(aa);
    led(0);
  }


  LcdCommandWrite(0x01); // 屏幕清空,光标位置归零
  lcd(" connect [OK]");

  clearBuff();
  Serial.println(ATCN);
  delay(500);
  while(Hand("OK")==0);

  while(1)
  {
    clearBuff();
    Serial.println(CREG_CMD);
    delay(500);
    readSerial(aa);

    if((strstr(aa,"0,1")!=NULL)||(strstr(aa,"0,5")!=NULL))
    {
      clearBuff();
      LcdCommandWrite(0x01); // 屏幕清空,光标位置归零
      lcd(" register [OK]");
      break;
    }
    else
    {
      LcdCommandWrite(0x01); // 屏幕清空,光标位置归零
      lcd(" register [..]");
      delay(500);
    }
  }
}


void send_english(void)
{
  clearBuff();
  Serial.println(CMGF1);
  delay(500);
  while(Hand("OK")==0);

  clearBuff();
  Serial.println(SEND_MESSA_TO_YOUR);
  delay(500);
  while(Hand(">")==0);

  Serial.println(SEND_MESSA_CONTENT);  //发短信内容
  delay(100);
  Serial.print("\x01A");      //发送结束符号
  delay(10);

  delay(1000);
  while(Hand("OK")==0);
}



void send_call(void)
{
  clearBuff();
  Serial.println(CALL_YOU_TELNUMBER); //打电话
  delay(2000);
  while(Hand("OK")==0);
}



void setup (void) {
  int i = 0;
  for (i=Enable; i <= DI; i++) {
    pinMode(i,OUTPUT);
  }
  delay(100);
  // 短暂的停顿后初始化LCD
  // 用于LCD控制需要
  LcdCommandWrite(0x38); // 设置为8-bit接口,2行显示,5x7文字大小
  delay(64);
  LcdCommandWrite(0x38); // 设置为8-bit接口,2行显示,5x7文字大小
  delay(50);
  LcdCommandWrite(0x38); // 设置为8-bit接口,2行显示,5x7文字大小
  delay(20);
  LcdCommandWrite(0x06); // 输入方式设定
  // 自动增量,没有显示移位
  delay(20);
  LcdCommandWrite(0x0E); // 显示设置
  // 开启显示屏,光标显示,无闪烁
  delay(20);
  LcdCommandWrite(0x01); // 屏幕清空,光标位置归零
  delay(100);
  LcdCommandWrite(0x80); // 显示设置
  // 开启显示屏,光标显示,无闪烁
  delay(20);

  Serial.begin(9600);//设置波特率为9600
  pinMode(ledpin,OUTPUT);//设置数字13 口为输出接

  Serial.println("serial port [ok]!");//显示“Hello World!”字符串
}
void loop (void) {
  LcdCommandWrite(0x01); // 屏幕清空,光标位置归零
  delay(10);
  LcdCommandWrite(0x80+3);
  delay(10);
  // 写入欢迎信息
  lcd("Welcome To");
  delay(10);
  LcdCommandWrite(0xc0+1); // 定义光标位置为第二行第二个位置
  delay(10);
  lcd("www.csgsm.com");
  delay(2000);

  AT();
  
  LcdCommandWrite(0x01); // 屏幕清空,光标位置归零
  lcd(" send sms [..]");
  send_english();
  
  LcdCommandWrite(0x01); // 屏幕清空,光标位置归零

  LcdCommandWrite(0x80+1); // 定义光标位置为第二行第二个位置
  lcd(CALL_YOU_TELNUMBER);
  delay(10);
  LcdCommandWrite(0xC0);
  delay(10);
  lcd(SEND_MESSA_CONTENT);
  
  send_call();
  delay(5000);

  LcdCommandWrite(0x01); // 屏幕清空,光标位置归零
  lcd(" Test over,thanks");
  while(1);
}

回复 支持 反对

使用道具 举报

发表于 2013-9-27 22:46:28 | 显示全部楼层
本帖最后由 long1225cn 于 2013-10-8 16:18 编辑

我还把代码改了控制我家的热水器,因为我经常出差10天以上,只要在我回来的路上提前1个小时发短信打开我的热水器,回家就直接可以洗澡了哦,我已经用了5个月了,没有发现什么问题!



回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-28 00:59:28 | 显示全部楼层
long1225cn 发表于 2013-9-27 22:19
自己用AT命令很灵活啊,官网的库函数换模块的时候就要去修改库函数了哦!
我都是自己写:
delay(3500);  ...

只用了I2C,舵机,红外的库函数啊,都是很方便的。你这里调用延时太多,我做的感觉靠延时去等待串口信号不可靠(你都没验证返回的“OK”),比如说gprs里要发送一个比较长的服务器IP信息,干等的话得不到返回信号,我是发了三遍(有时候一边发一边接收)在第二遍得到回复的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-28 01:03:45 | 显示全部楼层
long1225cn 发表于 2013-9-27 22:24
你的代码太像 创思通信的示例代码了!我不太会用指针,也不喜欢用哦!所有自己写了自己的代码!

一看就是行家,我也没说不是啊,本来就是在给的调试程序的基础上改的。本来是在自己写,但是字符串指针什么的老出错,索性就用了调试程序。他们这个readSerial函数读到换行回车就不读了,很不方便,本来想改,做成了之后感觉没意思了就不管了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-28 01:10:59 | 显示全部楼层
long1225cn 发表于 2013-9-27 22:16
原来你的是笔记本电脑,用陀机控制。我做的是台式办公电脑的远程开机,直接加个继电器并接至电脑的电源开关 ...

您的代码确实简单,这些string我看了好多,也试了很多,可能因为要实现的功能多一些,效果总出不来,一般都会先像你这样写。
回复 支持 反对

使用道具 举报

发表于 2013-9-28 20:40:11 | 显示全部楼层
哈哈,其实我是新手!因为一看就知道你的代码更像C代码风格!我的代码像玩Aduino风格!见笑了!
我控制热水器追求稳定,所以删除了很多以前做的检测电流电压,人体红外,门磁等等的代码!
回复 支持 反对

使用道具 举报

发表于 2013-9-28 20:48:59 | 显示全部楼层
只用了I2C,舵机,红外的库函数啊,都是很方便的。你这里调用延时太多,我做的感觉靠延时去等待串口信号不可靠(你都没验证返回的“OK”),比如说gprs里要发送一个比较长的服务器IP信息,干等的话得不到返回信号,我是发了三遍(有时候一边发一边接收)在第二遍得到回复的。

delay(3500);   开机等3.5S是个人的习惯,也就是等一切都稳定的意思!我职业的习惯吧!并不是等串口数据,这个是一开机第一条指令哦!

验证返回的“OK”,不用验证啊,我一开始也验证的,但我模拟调试从来不出问题,就删掉了哦!
两条命令中间加个延时就可以了!不加延时,GRPS模块有的时候会读不出Arduino发的命令!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-28 21:07:25 | 显示全部楼层
long1225cn 发表于 2013-9-28 20:48
只用了I2C,舵机,红外的库函数啊,都是很方便的。你这里调用延时太多,我做的感觉靠延时去等待串口信号不可 ...

呵呵,也许您的模块比较稳定吧,我的就。。。BTW,您做过红外发送实验吗,不是NEC码之类的(像我家电视东芝码的)编码接收到的Raw那串数字是变化的,怎么发送呢?自己写的发东芝码0xFF******根本没反应
回复 支持 反对

使用道具 举报

发表于 2013-9-28 22:16:21 | 显示全部楼层
红外发送没有做过啊!我做GSM这个都是为了去单位得QC奖项才做的哦!3000元现金,很爽的哦!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-29 00:21:26 | 显示全部楼层
long1225cn 发表于 2013-9-28 22:16
红外发送没有做过啊!我做GSM这个都是为了去单位得QC奖项才做的哦!3000元现金,很爽的哦!

{:3_50:}3K?!鼓励做这个的单位是好单位啊~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊 ( 浙ICP备09023225号 )

GMT+8, 2019-6-27 16:57 , Processed in 0.055578 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表