短信控制的 智能插头(sim900a arduino uno)

。_饼干妹妹 提交于 2019-12-14 17:11:43

https://www.arduino.cn/thread-19432-1-2.html

 

 1.所需工具:
(1)arduino UNO,(2)sim900a模块,(3)单路继电器,(4)220v ac转12v dc的降压模块【给arduino供电,12V是官方说明的供电极限】(我用的是高能立方),(5)插头,插孔,电线。

2.连线:
我是小白,不会设计电路,没法画图了,就直接说我自己的连线了。
火线接降压模块的L,零线接N,地线接E(插头遵守 左零右火上接地 原则);降压模块的正极接VIN,负极接GND;arduino 7脚接sim900a的5VR,8脚接sim900a的5VT;arduino的5V接sim900a的VCC,arduino的GND接sim900a的GND;arduino的11脚接继电器GND,12脚接继电器VCC,13脚接继电器的控制端;插孔的地线、零线接插头的地线、零线,插孔的火线一段接插头、一端接插孔、中间连入继电器。

3.注意事项:
(1)事先检查线有没有断(我就因为RX的线断了,折腾了好几天)
(2)保证sim卡安装好,sim卡的内容提前保存好程序会删除所有短信
(3)为了接收短信的全部内容可以增加串口缓冲区的大小,方法:找到Arduino\hardware\arduino\avr\libraries\SoftwareSerial\SoftwareSerial.h,里面有一行#define _SS_MAX_RX_BUFF 64 // RX buffer size。把64(或者其他数字)改大一点,我改成1024.

 

#include <SoftwareSerial.h>
 
//define Pins and Data
#define rxPin 8
#define txPin 7
#define relayPin 13
#define relayVCC 12
#define relayGND 11
#define relay_close  LOW
#define relay_open HIGH
enum SMStype {UNRELATED,OPEN,CLOSE,ASK};
 
//globle variable
SoftwareSerial m_serial(rxPin,txPin);
String MSG("");
String SMS("");
char myRelay=1;
char myPhone[]={"18843109531"};
char snd_tips[]={"Send open to open. Send close to close. Send ask to get the status. Case-Insensitive!"};
char snd_unrelated[]={"Sorry.I can't understand what you sent!"};
char snd_open[]={"The Plug has been Opened!"},snd_close[]={"The Plug has been Colsed!"},snd_ask_o[]={"The Plug is Opening..."},snd_ask_c[]={"The Plug is Closing..."};
 
//function declaration
void init(SoftwareSerial &p_serial);                                            //initialize the sim900a module
void getMSG(String &p_MSG,SoftwareSerial &p_serial);                            //get the sim900a module's message
bool chkMSG(String &p_MSG);                                                     //check the message's type
void rcvSMS(String &p_SMS,SoftwareSerial &p_serial);                            //recieve the first SMS
char chkSMS(String &p_SMS);                                                     //check the SMS's type
void sndSMS(const char *phone_num,const char *content,SoftwareSerial &p_serial);//send Short Message
void openRelay(char relay_VCC,char relay_GND);
void ctrlRelay(char relayType);                                                 //contral the relay
 
//main function
void setup() {
  openRelay(relayVCC,relayGND);
  init(m_serial);
  ctrlRelay(relayPin,relay_open);
  sndSMS(myPhone,snd_tips,m_serial);
}
 
void loop() {
  delay(100);
  getMSG(MSG,m_serial);
  //delay(100);
  if(!chkMSG(MSG))
    return;
  rcvSMS(SMS,m_serial);
  delay(100);
  switch(chkSMS(SMS))
  {
    case OPEN:
    {
      myRelay=relay_open;
      sndSMS(myPhone,snd_open,m_serial);
      delay(100);
      break;
    }
    case CLOSE:
    {
      myRelay=relay_close;
      sndSMS(myPhone,snd_close,m_serial);
      delay(100);
      break;
    }
    case ASK:
    {
      if(myRelay)
      {
        sndSMS(myPhone,snd_ask_o,m_serial);
        delay(100);
      }
      else
      {
        sndSMS(myPhone,snd_ask_c,m_serial);
        delay(100);
      }
      break;
    }
    default:
    {
      sndSMS(myPhone,snd_unrelated,m_serial);
      delay(100);
      sndSMS(myPhone,snd_tips,m_serial);
      delay(100);
    }
  }
  ctrlRelay(relayPin,myRelay);
}
 
void init(SoftwareSerial &p_serial)
{
  p_serial.begin(9600);
  p_serial.println("AT");
  delay(500);
  p_serial.println("AT+CMGD=1, 4");
  delay(500);
  p_serial.flush();
  delay(100);
}
 
void getMSG(String &p_MSG,SoftwareSerial &p_serial)
{
  p_MSG="";
  while(!p_serial.available()) ;
  for(char in='\0',flag=0;p_serial.available();)
  {
    in=p_serial.read();
    if(in=='+')
      flag=1;
    if(flag&&((in=='\r')||(in=='\n')))
      break;
    if(flag)
      p_MSG+=in;
  }
  p_MSG.trim();
  p_serial.flush();
}
 
bool chkMSG(String &p_MSG)
{
  for(int p_begin=0;(p_begin+5)<p_MSG.length();p_begin++)
  {
    if(p_MSG.substring(p_begin,p_begin+5)=="+CMTI")
      return true;
  }
  return false;
}
 
void sndSMS(const char *phone_num,const char *content,SoftwareSerial &p_serial)
{
  p_serial.println("AT");
  delay(500);
  p_serial.println("AT+CSCS=\"GSM\"");
  delay(500);
  p_serial.println("AT+CMGF=1");
  delay(500);
  p_serial.print("AT+CMGS=\"");
  p_serial.print(phone_num);
  p_serial.println("\"");
  for(;m_serial.read()!='>';) ;
  p_serial.print(content);
  delay(500);
  p_serial.write(0x1A);
  delay(500);
  p_serial.flush();
  delay(100);
}
 
void rcvSMS(String &p_SMS,SoftwareSerial &p_serial)
{
  p_SMS="";
  m_serial.println("AT");
  delay(500);
  m_serial.println("AT+CSCS=\"GSM\"");
  delay(500);
  m_serial.println("AT+CMGF=1");
  delay(500);
  m_serial.flush();
  m_serial.println("AT+CMGR=1");
  delay(500);
  while(!p_serial.available()) ;
  for(char in='\0',flag=0;p_serial.available();)
  {
    in=p_serial.read();
    if(in=='\"')
      flag++;
    if(flag==8)
    {
      p_serial.read();
      p_serial.read();
      while((in!='\r')&&(in!='\n')&&p_serial.available())
      {
        in=p_serial.read();
        p_SMS+=in;
      }
      break;
    }
  }
  p_serial.println("AT+CMGD=1, 4");
  delay(500);
  p_serial.flush();
  delay(100);
}
 
char chkSMS(String &p_SMS)
{
  String temp_open="open\r",temp_close="close\r",temp_ask="ask\r";
  
  if(p_SMS.equalsIgnoreCase(temp_open))
    return OPEN;
  if(p_SMS.equalsIgnoreCase(temp_close))
    return CLOSE;
  if(p_SMS.equalsIgnoreCase(temp_ask))
    return ASK;
  return UNRELATED;
}
 
void openRelay(char relay_VCC,char relay_GND)
{
  pinMode(relay_VCC,OUTPUT);
  digitalWrite(relay_VCC,HIGH);
  pinMode(relay_GND,OUTPUT);
  digitalWrite(relay_GND,LOW);
}
 
void ctrlRelay(char p_pin,char relayType)
{
  pinMode(p_pin,OUTPUT);
  digitalWrite(p_pin,relayType);
}

  5.代码解释
(1)之所以用软串口,是因为硬串口用来查bug。
(2)sim900a模块发送短信流程:
首先要同步波特率,给sim900a发送“AT\r”,详见init()。//应该是一次就行
发送英文短信要设置GSM字符集设置文本模式发送“AT+CMGS=\"188xxxxxxxxx\"\r"(188xxxxxxxx是手机号)
等模块返回">"后,发送短信内容不要加\r或\n
最后发送16进制的0x1A(注意是16进制的,不要发送成字符)
然后就发送成功了,详见sndSMS()。
(3)sim900a模块接收短信流程
sim900a模块接收到短信后会给arduino发送含有”+CMTI"的字符串
要设置GSM字符集
设置文本模式
发送”AT+CMGF=1"查询第一条短信,=2就查询第二条以此类推
在sim900a返回的字符中查找短信的内容,第8个 “ 后就是短信内容

6.还需改进
(1)在chkSMS()中可以判断短信内容,为了安全考虑,可以在短信内加入密码(如sim卡的pin),如发送“pin码+open”表示打开。
(2)未来可以做一个有收发短信功能的手机app,还可以实现定时开关(定时发送短信)。

 

 

#include<SoftwareSerial.h>
SoftwareSerial softSerial1(4,5);//软串口RXD4、TXD5,与短信模块通信
#define yudi_d 2    //水传感器口
#define relay 3     //继电器口
unsigned long previousMillis=0;//存储时间,用于计时
const long interval=10000; //短信间隔10000ms
int flag=0;//出水短信发送

 int sendMeg(String phonenum,String text)//发送信息的函数,直接调用即可,无需修改
  {
        char comdata=0;//判断接收到的最后一位是否对
        String phone="";//电话号码存储
        phone="AT+CMGS=\""+phonenum+'\"';   
         while (softSerial1.available() > 0){
        comdata = softSerial1.read();  //每次读一个char字符,并相加
        delay(2);
        }    
        softSerial1.println("AT");//对GSM发送AT,看响应
        delay(1000);
        while (softSerial1.available() > 2){
        comdata = softSerial1.read();  //每次读一个char字符,并相加
        Serial.print(comdata);//错误
        delay(2);
        }
        if(comdata!='K')//判断没有收到OK
        {
        Serial.println("error1");//错误
//        return  0;
        }
        comdata=0;     
        softSerial1.println("AT+CMGF=1");//设置GSM文本模式
        delay(500);
        while (softSerial1.available() > 2){
        comdata = softSerial1.read();  //每次读一个char字符,并相加
        delay(2);
        }
        
        if(comdata!='K')//没有收到OK
        {
        Serial.println("error2");
//        return  0;
        } 
        comdata=0;
        softSerial1.println(phone);//发送的目标号码
        delay(1000);
        while (softSerial1.available() > 1){
        comdata = softSerial1.read();  //每次读一个char字符,并相加
        delay(2);
        }
        
        if(comdata!='>')//没有收到>
        {
        Serial.println("error3");
//        return  0;
        }
        comdata=0;
        softSerial1.print(text);//发送所写内容
        delay(500);
        softSerial1.write(0x1A); //结束输入文本,并发送
        Serial.println("success");  //成功   
    
 }
void setup(){
   
Serial.begin(9600);//串口
softSerial1.begin(9600);
    //监听软串口通信
softSerial1.listen(); 
pinMode(A7,INPUT);//水传感器模拟端口设置模式
pinMode(relay,OUTPUT);//继电器端口模式
pinMode(yudi_d,INPUT);//水传感器数字端口设置模式
}
  
void loop(){
 unsigned long currentMillis=millis();//当前时间,用于判断时间
 int a0= analogRead(A7);//获取模拟端口值
//Serial.print(a0); 
//Serial.print("--");//串口输出,主要用于电脑监视和调试
 
int d2=digitalRead(yudi_d);//获取数字端口值
//Serial.println(d2);//串口输出,主要用于电脑监视和调试
if(d2==0)//判断是否浸入水中
digitalWrite(relay,LOW);//进入,打开继电器
else
digitalWrite(relay,HIGH);//未进入,关闭
if(d2==0&&currentMillis-previousMillis>=interval)//浸入水中,并时间间隔大于10s
{
  previousMillis=currentMillis;//获取当前时间,以便于为下次发短信计时
  sendMeg("15147300333","Water logging alarm of No.2 well of 110kV gold lead cable tunnel, please handle it quickly");//给15147300333  发送信息
  Serial.println("1");  //成功 
  flag=1;
}  
if(d2==1&&flag==1)//出水
{
  delay(2000);
  sendMeg("15147300333","The water logging alarm of No.2 well of 110kV gold lead cable tunnel has been removed.the equipment is normal");//给15147300333  发送的信息
  Serial.println("2");  //成功 
  flag=0;
  }
delay(100);
}

  

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!