环境数据采集系统——中期总结
一个月就这么快的过去了,回首这一个月感觉还是很充实的,现在回想一下这一个月的收获吧。
这一个月我接触了很多以前没有接触到得东西,收获不可谓不大。7月5号开始,我开始做环境数据采集系统,在这之前我还没有亲手接触过arduino,知识仅仅局限在书本的介绍。
和我当初的构想差不多,因为在开题报告的时候也了解了很多,所以脑子里的构思还是很清楚的。我把整个系统构思分为三个部分:采集终端、数据节点、服务器及客户端。
将数据采集放在采集终端,然后将采集终端的数据发送到数据节点;数据节点又把数据初步处理然后通过移动数据网络传输到internet;服务器将已经传入网络的数据进行处理,生成数据视图;最后可以通过web或者其他客户端访问服务器提取数据就可以清晰的看到数据了。
用户还可以通过web或者客户端向服务器发送指令,指令在传输至节点,节点将指令发送到控制器,通过程序的预设实现各种功能,实时控制整个采集系统。
一。 采集终端:
这一个月我基本是把采集终端弄好了,采集终端已经能够采集数据了还在里面加了串口传输和lcd显示。在电脑端可以通过串口看到数据,也已经可以在电脑端出处理数据,也做了测试,也对数据做了测试,数据基本全部正常;此外,因为添加了lcd,所以采集终端系统可以脱离电脑串口直接在lcd上直观查看数据。现在采集终端只需要提供单独的供电就可以脱离电脑工作了,arduino需要5v电源,而风速风向则需要7~24v的外接电源供电,只有有这两个电源就可以很方便的工作了。
现在采集终端包含了许多的设备:arduino INO控制器、风速、风向传感器、温湿度传感器、光照传感器、粉尘灰尘传感器、紫外线传感器、土壤温湿度传感器、无线串口等等。将代码写入uno控制器,然后连接传感器就可以控制传感器了,可以单个实现传感器功能,也可以将多个传感器集成在一个控制器上形成一个采集系统。还可以在采集系统上添加许多通信模块实现数据传输通信,通信模块其实也很多,比如说:无线通信模块,红外模块,GSM/GPRS模块,蓝牙模块,WiFi模块等等。
下面先说说我用上的采集终端传感器吧:
1、光照传感器:光照传感器核心原理就是通过光敏电阻或者光敏二极管三极管来感应光的大小强度,将其感应到的光照强度转化成电压,最后输出电压。光敏电阻体就是在电极上加上电压,设备开启电极间有电流流通,受到适当波长光线照耀时,电流就会随着光照强度的变化而变化,从而实现光电的转化。我使用的传感器就为光敏电阻器电源为3—5V电压驱动,直接可以使用UNO控制器的电源驱动,传感器内置16bitAD转换器,遵守标准NXP IIC通信协议,模块内部包含通信电平转换,与5V单片机Io直接连接,Features I2C 总线接口(f / s模式支持),使用非常方便,而且光源的依赖性不大(例如白炽灯.荧光灯.卤素灯.白LED),小测变异(+/- 20%)13)的红外线的影响很小.处理值也很精确。
编程比较简单,需要添加一个BH1750FVI和Wire的函数库,再调用SetAddress,SetMode、GetLightIntensity等几个函数得到需要的电压值,并通过转化器和换算得到需要的光照强度。
示例程序:
- #include <Wire.h> //IIC连接库
- #include <BH1750FVI.h> //光照的库函数
- BH1750FVI LightSensor; //定义光照对象
- void setup()
- {
- Serial.begin(9600); //设置串口频率
- LightSensor.begin(); //对象LightSensor以主机身份加入通信
- LightSensor.SetAddress(Device_Address_H); //设置通信地址
- LightSensor.SetMode(Continuous_H_resolution_Mode); //设置引脚
- Serial.println("Running..."); //初始化完成提示语
- }
- void loop()
- {
- // put your main code here, to run repeatedly:
- uint16_t lux = LightSensor.GetLightIntensity();// 得到紫外线的值
- Serial.print("Light: "); //串口输出提示信息和值
- Serial.print(lux);
- Serial.println(" lux");
- delay(1000);
- }
2、风向传感器:风向传感器有一个风向信号发生装置,由风标转轴带动一个有6个格雷码光盘的发生装置,发生装置内部每个光盘有6位格雷码,相邻的部分做了透光于不透光处理。通过位于码盘两侧同一半径上6对光电耦合器输出相应的6位格雷码,码盘上安装了36个红外发光二极管下面有6个光电转换器,都正对码盘的6个轨道。风向变动,码盘下面的光电管接收到的电码发生变化,每一个格雷码代表一个风向,分辨率为5,61.4度。
此外风向公式为: WD(风向) = K(分辨率)* GM(格雷码) 。 //格雷码算法
WD风向值=(输出电压-0.4)/16*360 //电压算法,输出电压上升0.1V对应风向顺时针转移一个方向
传感器有格雷码、电压、电流三种输出方式,因为我使用的UNO控制器对电压的处理非常方便,所以使用此款arduino风向传感器, 风向传感器的规格为输入电压7~24V,输出电压为0.4~2v, 编程时要通过公式换算,将0.4~2v的输出电压模拟成控制器的0~5v输入电压范围。
- char* dirstring[16] = {"North","North1","Northeasterly","Northeasterly1","East","East1","Southeast","Southeast1","South","South1","Southwest","Southwest1","West","West1","Northwest","Northwest1"}; //设置16个风向
- void setup() {
- Serial.begin(9600);
- }
- void loop() {
- int sensorValue1 = analogRead(A0); //读取风向传感器
- float value1 = sensorValue1 * (5.0 / 1024.0); //换算公式,得到值
- //Serial.println(value1);
- int winddirection =( value1 *10) ;
- winddirection = winddirection - 4 ; //减去传感器自身电压底限值
- Serial.println(winddirection); //提示信息
- // if(winddirection < 0)
- // winddirection = 0;
- // if(winddirection > 15)
- // winddirection = 15;
- Serial.print("winddirection is ");
- if(winddirection == 0 || winddirection == 15 ) //解决电压误差问题
- { Serial.println( dirstring[0] );}
- else
- { Serial.println( dirstring[winddirection] );}
- delay(500);
- }
3、风速传感器: 风速传感器内部有一个光电子风速计,中心有不锈钢转动轴,内部连接了一个光盘,内部还有红外光速,不锈钢转动轴带动光盘转动,切割红外来实现计算风速。当风推动传感器上的碗推动转动轴,转动轴带动光盘转动,光盘每转动一次切割红外14次,从而有光电晶体产生一个脉冲链,实现信号的发生。脉冲链的速率与风速成正比。
风速换算公式: ws(风速m/s) = Vo(初始风速) - f(F)( 每秒计数值)
风速传感器是看着比较好玩,我也挺喜欢的玩的一个传感器之一,不过也是很简单的传感器,只要用控制器得到传感器的电压在通过公式运算就可以得到风速。
- void setup() {
- Serial.begin(9600);
- }
- void loop() {
- int sensorValue = analogRead(A2);
- // Serial.println(sensorValue);
- float value = sensorValue * (5.0 / 1024.0);
- // Serial.println(value);
- float fanspeed = value - 0.4 ;
- // Serial.print( fanspeed );
- fanspeed = fanspeed * 1.6*32.4 ;
- Serial.print("fanspeed is ");
- Serial.print( fanspeed );
- Serial.println( "m/s" );
- delay(500);
- }
4、温湿度传感器:温湿度传感器原理有三种:
热电阻:根据金属丝电阻随温度变化原理工作;
热电偶:两种导体接触块结点处稳定电势;同导体两端温度同两端间定电势;
液体温度计:利用温液体受热膨胀原理工作。
三种传感器都是通过自身感应原理将感应到的温湿度信息转化成数据信号,在通过相应的公式换算成有实际意义的数据值。其中电阻式感应器比较常用。
我使用的是TH22数字温湿度传感器,DHT22数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。单线制串行接口,系统集成十分简易快捷,连接方便,可直接插接到Arduino传感器扩展板上。
温湿度传感器的编程和连线都很简单,需要DHT22的函数库,需要函数读取传感器传出的值就ok了。
5、土壤温湿度传感器:土壤型温湿度传感器的基本检测原理与温湿度传感器基本原理相似,只不过土壤温湿度传感器的工作环境为湿度较高的土壤,为了保护感应原件和确保数据的准确性,所以得添加特殊的保护装置。
我使用的数字温湿度传感器系列中土壤型专用传感器,它把传感元件和信号处理集成起来,输出全标定的数字信号。传感器包括一个电容性聚合体测湿敏感元件、一个用能隙材料制成的测温元件,并在同一芯片上,与14 位的A/D 转换器以及串行接口电路实现无缝连接。每个传感器芯片都在极为精确的湿度腔室中进行标定,校准系数以程序形式储存在OTP 内存中,在标定的过程中使用。传感器在检测信号的处理过程中要调用这些校准系数。两线制的串行接口与内部的电压调整,使外围系统集成变得快速而简单。
数字温湿度传感器除了常规的VCC和GND接口外,特殊的接口为:黄色 SCK 时钟 信号 兰色 D ATA 数据输出。数字温湿度传感器除了探测温湿度外还可以计算露点。
- #include <Sensirion.h>
- const uint8_t dataPin = 2; //定义数据接口<span style="white-space:pre"> </span>
- const uint8_t clockPin = 3; //时钟接口
- float temperature; //温度
- float humidity; //湿度<span style="white-space:pre"> </span>
- float dewpoint; //露点
- Sensirion tempSensor = Sensirion(dataPin, clockPin); //创建一个温湿度对象
- void setup()
- {
- Serial.begin(9600);
- }
- void loop()
- {
- tempSensor.measure(&temperature, &humidity, &dewpoint); //使用对象内部函数获得数据
- Serial.print("Temperature: "); //显示数据
- Serial.print(temperature);
- Serial.print(" C, Humidity: ");
- Serial.print(humidity);
- Serial.print(" %, Dewpoint: ");
- Serial.print(dewpoint);
- Serial.println(" C");
- delay(5000);
- }
6、粉尘传感器:一般粉尘传感器的原理大致为:外部含尘空气吸引下进入吸引口,经导流装置(遮掉外部光线)进入检测器暗室。暗室内的平行光与受光部的视野成直角交叉构成灵敏区(图中斜线部分),粉尘通过灵敏区时,其90℃方向散射光透过狭缝射进来由光电倍增管接收并转换成光电流,经光电流积分电路转换成与散射光成正比的脉冲电信号,计算出粉尘的质量浓度信号输出。
我使用的是PPD42NS粉尘传感器,该传感器为PWM方式输出,结构紧凑,重量轻,光学原理,能够探测1微米以上的粉尘粒子。此外,这个传感器还有两种输出模式,解决不同灵敏度使用要求,洁净环境Vout输出高电平信号(4V)。对应的接线为VCC->PIN3,GND->PIN1,受控角->pin5;而pin2和pin4则为两种模式输出,pin4为设定好的信号输出脚,最小检测颗粒为1μm,而pin2则为可调灵敏度输出教,默认的灵敏度为最小2.5μm,可以通过pin5控制脚来手动调节灵敏度。此外,粉尘传感器的运行周期大约为30S,
30S为一个读取粉尘的周期
- int pin = 8;
- unsigned long duration;
- unsigned long starttime;
- unsigned long sampletime_ms = 30000;
- unsigned long lowpulseoccupancy = 0;
- float ratio = 0;
- float concentration = 0;
- void setup() {
- Serial.begin(9600);
- pinMode(8,INPUT);
- starttime = millis();
- }
- void loop() {
- duration = pulseIn(pin, LOW); //duration 为输入的电压值
- lowpulseoccupancy = lowpulseoccupancy+duration; // 电压值
- if ((millis()-starttime) > sampletime_ms) //如果运行时间大于30S执行
- {
- ratio = lowpulseoccupancy/(sampletime_ms*10.0); // Integer percentage 0=>100 ratio比值 = 运行时间/300.0s
- concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve 使用规范曲线计算值
- Serial.print(ratio); //比值
- Serial.print(",");
- Serial.println(concentration); //计算值
- lowpulseoccupancy = 0;
- starttime = millis();
- }
- }
7、紫外线传感器:紫外线传感器由于非常简单,所以是做得最快的一个,主要麻烦的是在编程方面,紫外线传感器会根据外界紫外线的强度输出一个电压值,通过arduino板子读取其引脚所输出的电压,在经过一定的换算即可得到想要的紫外线强度的值。我们用analogRead()函数读取其引脚的电压值。在这里需要注意的是,紫外线的级数,从紫外线传感器读取的电压值,还需要经过转换才能得到紫外线强度。
紫外线传感器主要功能是采集空气中紫外线强度,这里使用UVM-30A紫外线传感器模块,具有准确度高,造价相对较低的特点。 使用时,将其“+”号接口接到arduino UNO板子的5v接口上,将其“—”号接口接到arduinoUNO 板子上的GND接口上,将其”out“号接口接到板子的A0引脚上,插上电源,把事先写好的程序下载到板子上,一个紫外线传感器就接好了。
- void setup()
- {
- pinMode(3,INPUT);
- Serial.begin(9600);
- }
- void loop()
- {
- int a= analogRead(3); //读取传感器返回电压值
- if(0<=a && a<=50)
- {
- Serial.print("The UV index is: "); //给各种不同返回值设置紫外线等级
- Serial.println(0);
- }
- else if(50<a && a<=227)
- {
- Serial.println("The UV index is: ");
- Serial.print(1);
- }
- else if(227<a && a<=318)
- {
- Serial.print("The UV index is: ");
- Serial.println(2);
- }
- else if(318<a && a<=408)
- {
- Serial.print("The UV index is: ");
- Serial.println(3);
- }
- else if(408<a && a<=503)
- {
- Serial.print("The UV index is: ");
- Serial.println(4);
- }
- else if(503<a && a<=606)
- {
- Serial.print("The UV index is: ");
- Serial.println(5);
- }
- else if(606<a && a<=696)
- {
- Serial.print("The UV index is: ");
- Serial.println(6);
- }
- else if(696<a && a<=795)
- {
- Serial.print("The UV index is: ");
- Serial.println(7);
- }
- else if(795<a && a<=881)
- {
- Serial.print("The UV index is: ");
- Serial.println(8);
- }
- else if(881<a && a<=976)
- {
- Serial.print("The UV index is: ");
- Serial.println(9);
- }
- else if (976<a && a<=1079)
- {
- Serial.print("The UV index is: ");
- Serial.println(10);
- }
- else
- {
- Serial.print("The UV index is: ");
- Serial.println(11);
- }
- delay(1000);
- }
8、lcd显示器:LCD等显示器都是由多个显示点构成,通过每个显示点显示不同的颜色来实现显示文字和图案的功能。迷你12864液晶显示模块这款模块SPI为接口的显示模块,配合12864LCD库文件,便可轻松显示汉字,字符和图形。并有背光LED控制,可使显示效果更美观。可显示128列×64行点阵单色图片,可显示16×16点阵和12×12点阵汉字及图片,可显示8字/行×4行(16×16点阵汉字),可显示16字/行×8行(8×8点阵的英文、数字、符号)。采用3线SPI串行接口以及一条命令/数据控制线,最多只需5个端口(3线SPI接口加命令/数据控制线,再加上复位信号线)。
- #include "U8glib.h"
- U8GLIB_MINI12864 u8g(13, 11, 10, 9, 8); //SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9 ,RST=8;
- void draw(void) {
- u8g.setFont(u8g_font_unifont);
- u8g.drawStr( 0, 22, "temperture: ");
- u8g.drawStr( 0, 40, "32");
- }
- void setup(void) {
- }
- void loop(void) {
- u8g.firstPage();
- do {
- draw();
- } while( u8g.nextPage() );
- delay(500);
- }
引脚定义:
标示符号 名 称 功 能
R RESET 低电平复位,复位完成后,回到高电平,液晶模块开始工作。如果不需软件给芯片复位,可不连接
A A0 数据和命令选择。L:命令 H:数据
CS CS SPI 片选(内部已拉高),低有效
C SCK 串行时钟
D MOSI(SID) 数据传输
- GND 电源地
+ VCC DC 3.3V~5.5V
L LED 背光LED使能,低有效
该显示器要使用必须得添加Lcd12864或者u8g库文件。
Lcd12864是点阵式显示,只能显示点阵信息,可以用于显示图片,但是需要下载一个字模软件,设计一个 128×64 的字符点阵图形。字模软件可以手动输入或是自画,还可以引用pin格式的图画画点阵,字模软件将输入的信息转化成字符点阵图形后就可以使用Lcd12684库函数调用来显示信息和图片了。使用该函数库得遵守spi协议。
u8g库文件主要是针对显示数据而设计,使用u8g函数可以很方便的显示浮点数,字符串等数据,还可以灵活的设置显示位置,非常方便。不过值得注意,使用u8g后,要显示数据调用print函数之前还得先调用设置字体和设置显示位置u8g.setFont (); u8g.setPrintPos ();的函数。
二、传输节点:
传输节点的存在就是为了解决各个传感器系统的数据向外传输问题,也可以接收服务器下传的指令。我的传输节点由一个uno控制器 + 一个无线传输模块 + 一个GSM/GPRS扩展版组成;无线传输模块接收来自采集终端的数据,采集终端将数据传入控制器进行处理;最后控制器在发送指令将数据通过GSM/GPRS模块上传至internet。
无线串口:
模块是高度集成半双工微功率无线数据传输模块,其嵌入高速单片机和高性能射频芯片。创新的采用高效的循环交织纠检错编码,抗干扰和灵敏度都大大提高,最大可以纠24bits连续突发错误。APC220模块提供了多个频道的选择,能够透明传输任何大小的数据,而用户无须编写复杂的设置与传输程序,并提供UART/TTL接口。同时小体积,宽电压运行,较远传输距离,丰富便捷的软件编程设置功能,使APC220模块能够应用与非常广泛的领域。
PC220模块的组网应用 APC220的通信信道是半双工的,可以完成一点对一点,一点对多点的通讯。这二种方式首先需要设1 个主站,其余为从站,所有站点都必须设置一个唯一的地址。通信的协调由主站控制,主站采用带地址码的数据帧发送数据或命令,所有从站全部都接收,并将接收到的地址码与本机地址码比较,地址不同则将数据丢掉,不做响应,若地址码相同,则将接收的数据传送出去。以上过程可以通过软件设置NET ID和NODE ID自动实现,也可有用户通过上层协议完成。当设置NET ID和NODE ID时,APC220模块将自动比较所接收数据是否地址匹配,但不会自动应答,若地址匹配模块会将地址、数据传给终端设备。另外,组网必须保证在任何一个瞬间,同一个频点通信网中只有一个电台处于发送状态,以免相互干扰。APC220可以设置多个频道,所以可以在一个区域实现多个网络并存。
特点:
1000米传输距离(2400bps)
工作频率418-455MHz(1KHz步进)
大于100个频道
GFSK的调制方式
高效的循环交织纠错编码
灵活的软件编程选项设置
UART接口,RS232/RS485可定制。
超大的256bytes数据缓冲区
适合大数据量传输
内置看门狗,保证长期可靠运行
性能描述:
工作频率 415MHz to 455MHz (1KHz步进)
调制方式 GFSK
频率间隔 200KHz
发射功率 20mw (10级可调)
接收灵敏度 -117dBm@1200bps
空中传输速率 1200 - 19200bps
接口速率 1200 - 57600bps
接口效验方式 8E1/8N1/8O1
接口缓冲空间 512bytes
工作湿度 10%~90%(无冷凝)
工作温度 -20℃ - 70℃
电源 3.3 – 5.5V (±50mV 纹波)
发射电流 ≦35mA@10mW
接收电流 ≦30mA
休眠电流 ≦5uA
传输距离 1000米传输距离 (开阔地可视距离)
尺寸 37mm x 17mm x 6.5mm
引脚定义:
引脚 定义 说明
1 GND 地,0V
2 VCC 3.3V—5V
3 EN 电源使能端,≧1.6V或悬空使能,≦0.5V休眠
4 RXD UART输入口,TTL电平
5 TXD UART输出口,TTL电平
6 AUX UART收发指示输出,接收为低,发送为高
7 SET 设置参数,低有效
通过USB-UART模块可以很简单的相互通信。接下来我又使用了控制器来连接无线串口,先将控制器烧空,然后连接uno控制器上的pin1和pin2两个传输和接收引脚 ,使用硬串口实现相互通信。后来又使用了多个无线串口,在同一个频点下,同样的speed,一点发出数据,其他所有点都可以接收数据,这样就可以实现多组数据采集端向一个节点发送数据了。但是串口容易出现乱码,这是不太好的问题。
下面是我用粉尘和风速测试串口的程序,里面的数据就可以用无线串口发送:
- int pin_fc = 3;
- char s[16][6] = {"N","NE->N","NE","NE->E","E","SE->E","SE","SE->S","S","SW->S","SW","SW->W","W","NW->W","NW","NW->N"};
- unsigned long duration;
- unsigned long starttime;
- unsigned long sampletime_ms = 30000;//sampe 30s ;
- unsigned long lowpulseoccupancy = 0;
- float ratio = 0;
- float concentration = 0;
- int windsprrd = 0;
- int sensorValue;
- int a;
- void setup()
- {
- Serial.begin(9600);
- pinMode(pin_fc,INPUT);
- starttime = millis();//get the current time;
- }
- void loop()
- {
- sensorValue = analogRead(A3);
- a = analogRead(A0);
- duration = pulseIn(pin_fc, LOW);
- Serial.println("The Wind Speed && Direction :");
- wind_speed();
- wind_direction();
- lowpulseoccupancy = lowpulseoccupancy+duration;
- fenc();
- lowpulseoccupancy = 0;
- starttime = millis();
- delay(10000);
- }
- void wind_speed()
- {
- float fanspeed= (sensorValue * (5.0/1024.0) - 0.4) * 1.6 * 32.4;
- Serial.print(fanspeed);
- Serial.println("m/s;");
- if (fanspeed>0 && fanspeed<1.555)
- windsprrd = 1;
- else if (fanspeed>1.555 && fanspeed<3.405)
- windsprrd = 2;
- else if (fanspeed>3.405 && fanspeed<5.495)
- windsprrd = 3;
- else if (fanspeed>5.495 && fanspeed<7.995)
- windsprrd = 4;
- else if (fanspeed>7.995 && fanspeed<10.755)
- windsprrd = 5;
- else if (fanspeed>10.795 && fanspeed<13.805)
- windsprrd = 6;
- else if (fanspeed>13.805 && fanspeed<17.199)
- windsprrd = 7;
- else if (fanspeed>17.199 && fanspeed<20.705)
- windsprrd = 8;
- else if (fanspeed>20.705 && fanspeed<24.455)
- windsprrd = 9;
- else if (fanspeed>24.455 && fanspeed<28.455)
- windsprrd = 10;
- else if (fanspeed>28.455 && fanspeed<32.655)
- windsprrd = 11;
- else
- windsprrd = 12;
- Serial.print(windsprrd);
- Serial.println("ji;");
- }
- void wind_direction()
- {
- int winddirection =( a * (5.0 / 1024.0) *10) - 4 ;
- // float b = winddirection/16.0*22.5;
- //Serial.print(b);
- //Serial.print( "The wind direction :");
- if(winddirection == 0 || winddirection == 15 )
- { Serial.println( s[0] );}
- else
- { Serial.println( s[winddirection] );}
- }
- void fenc()
- {
- if ((millis()-starttime) > sampletime_ms)//if the sampel time == 30s
- {
- ratio = lowpulseoccupancy/(sampletime_ms*10.0); // Integer percentage 0=>100
- concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve
- Serial.println("The fencheng is :");
- Serial.print(lowpulseoccupancy);
- Serial.print(",");
- Serial.print(ratio);
- Serial.print(",");
- Serial.println(concentration);
- }
- }
GSM/GPRS模块:
到sim900模块了,这个模块其实是个很有意思的模块,加上控制器和显示器基本算是一个小手机了,可以语音通话,发送短信,最主要的是还可以GPRS上网,所以很适合拿来做数据传输节点。我们用的模块是已经封装好了的模块,模块内部集成了各种指令,只需要用户调用各种指令就可以自动实现各种功能了。这个模块需要配合一张2G的sim卡来配合打电话发短信以及上网功能的实现。
模块指令的格式基本为AT+" ",发送完指令后模块会向返回一个反馈信息,例如拨打电话指令发送成功后会返回“OK”,如果不成功则返回“ERROR”。向模块发送AT指令在我理解有三种方式,第一种是电脑加连接线硬串口连接输入AT指令;第二种使用软串口通过电脑端向模块发送指令;第三种通过程序写入控制器,控制器程序向模块发送指令。
模块的功能大概分为三种:打电话、发信息、GPRS上网。打电话的功能非常简单,只需要一个简单的<ATD"电话号码";>就可以实现功能了,而发信息和打电话则要复杂得多了。
短信步骤:
1、需要设置发送模式,选择文本格式还是PUD模式;
2、设置文本发送模式的参数;
3、设置为 UCS2 编码字符集;
4、将所需发送的内容和电话号码转换为UNICODE 编码;
5、发送: AT+CMGS=“电话号码UNICODE 编码”,等待返回‘>’字符;
6、等到返回'>'字符后,输入内容的UNICODE 编码,再发送一个十六进制的OX1A发送信息。
上网的设置更加复杂,进行 GPRS 通信,实现模块与电脑的
TCP 和 UDP 数据传输。这里将要用到的指令有: 10 余条 AT 指令。需要选择联网模式、设置协议、设置端口、设置IP、等待返回‘>’字符输入内容、设置数据中心等等。
这里有些常用的AT指令:
测试信号质量,用串口发送下面的指令:
AT+CSQ
此时会收到形如下面这样的回复消息:
+CSQ: 11,0
OK
拨打电话(这条指令后的分号不可少),可以把下面指令里的10086,替换成其他号码。
ATD10086;(回车)
挂断电话
ATH
接听电话
ATA
发送短信
首先设置成文本模式:
AT+CMGF=1
设置使用模块默认的国际标准字母字符集发送短信
AT+CSCS?
发送目标号码
AT+CMGS=”10086″(回车)
此时系统会出现“>”提示符,直接输入短信内容
> YE
这条短信的目的是发送给10086,用来查询余额。
0x1A (16进制发送)
发送成功以后会收到系统如下提示,后面的数字表示发送短信的编号。
+CMGS: 115
OK
接收短信
如果接收到了短信,则系统会在串口输出如下的提示,后面的数字表示短信收件箱里的短信数目:
+CMTI: “SM”,2
发送如下AT指令,后面的数字是短信索引号。由于使用的是IRA编码,中文短信不能显示,可以发英文短信用来测试。
AT+CMGR=2
还有一些代码:
- 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=\"18382117086\"\r\n" //发短信接收的手机号码
- #define SEND_MESSA_CONTENT "http://shop69712475.taobao.com \n openjumper " //短信内容
- #define CALL_YOU_TELNUMBER "ATD18382117086;\r\n" //打电话接受的手机号码
- /*************************************************/
- 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++;
- }
- }
- }
- void clearBuff(void)//打电话发短信清除指令
- {
- for(j=0;j<MAXCHAR;j++)
- {
- aa[j]=0x00;
- }
- j=0;
- }
- 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;
- }
- 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)
- {
- Serial.begin(115200);//设置波特率为115200
- // Serial.println("serial port [ok]!");
- }
- void loop (void)
- {
- send_english(); //发短信
- delay(1000);
- send_call(); //打电话
- while(1);
- }
环境数据采集系统——中期总结相关推荐
- 基于ZigBee的物联网环境数据采集系统
1.概述 鉴于ZigBee技术适合用于数据采集系统的的特点, 提出了基于ZigBee的数据采集系统的设计方案, 着重探讨ZigBee节点的硬件设计及其组网设计. 并详细讨论了基于CC2530芯片的数据 ...
- 如何实现一平台多系统_自动化设备数据采集系统如何实现
在企业管理信息系统中,数据采集无疑是整个系统正常运作的一个关键.对于制造型企业,生产设备的工作状况和产量数据是管理信息系统中需要了解的基础数据之一.因此自动完成生产数据采集,可避免手工信息录入方式造成 ...
- stm32采集脉冲信号_基于STM32+FPGA的数据采集系统的设计与实现
引言 由于火控系统工作环境特殊,所需采集信号复杂多样,传统的以微控制器或PC为主的采集系统往往难以胜任.针对上述问题,提出了一种基于STM32+FPGA的数据采集系统的设计方案,该方案不仅能够完成对多 ...
- 数据采集系统的抗干扰措施
目录 1. 引言: 2.干扰的主要来源 3.系统抗干扰的硬件措施 4.系统抗干扰的软件措施 5.在PCB设计时用EDA软件对系统的EMC性能模拟仿真 6.噪声与干扰抑制措施 7. 结束语 原文地址:数 ...
- 基于STM32的光敏传感器数据采集系统-嵌入式系统与设计课程设计
目录 1 项目概述 1.1 项目介绍 1.2 项目开发环境 1.3 小组人员及分工 2 需求分析 2.1 系统需求分析 2.2 可行性分析 2.3 项目实施安排 3 系统硬件设计 3.1 系统整体硬件 ...
- 自动化设备数据采集系统优势
1 自动化设备数据采集系统优势 目前仍有许多工厂或企业生产指挥管理采用一种基于人工方式的报账手段,对生产过程中一些重要数据采集系统依靠岗位工的手工记录,形成日报表上报,依据日报表汇总后供上级部门分析和 ...
- 基于arduino与raspberry的远程数据采集系统
前言 该课题是毕业时做的一个远程数据采集课题,今天无意翻看到这份报告,不禁勾起满满的怀念.重新看了一遍报告,感觉做的确实是挺low的,但想起当时自己查了无数的资料,才完成这个设计,尤其是人在学校,然后 ...
- 基于FPGA的数据采集系统
目录 一.理论基础 二.核心程序 三.测试结果 一.理论基础 数据采集是指将模拟量采集转换成数字量后,再由计算机进行存储.处理.显示或打印的过程,相应的系统称为数据采集系统.随着科技进步,人们对数据采 ...
- 基于MQTT的数据采集系统
基于MQTT的数据采集系统 1.实验目的 本次研究推出一款实用的轻量型智能家居系统,本系统采用STM32为主控芯片,将MQTT通信协议移植到STM32中,将其作为一个MQTTClient.该系统的核心 ...
最新文章
- Design Pattern: Observer Pattern
- delphi 到出execl2010 文件损坏_Win7系统出现explorer.exe损坏的图像的解决方法是什么?...
- [Jarvis OJ - PWN]——[XMAN]level2
- python123查找指定字符输入m_大数据应用人才培养系列教材 Python语言 刘 鹏 张 燕 总主编 李肖俊 主编 刘 河 钟 涛 副主编....
- Dapr闪电说 - Dapr落地云原生架构
- linux守护进程fifo,linux守护进程配置文件
- 安卓逆向_22( 一 ) --- Xposed【 Android Studio + Xposed 实现简单的 hook 】
- 精化集ASP.NET AJAX与ASP.NET MVC分类第二轮筛选结果
- 快看,我们的分布式缓存就是这样把注册中心搞崩塌的!
- Fragment的一些基础
- docker部署flask服务方法
- 一个简单的爬虫例子(代码)
- celery异步发送邮箱
- [Step By Step]SAP HANA PAL 数据处理四分位间距检测Inter-quartile Range Test范例IQRTEST
- Codeforces 985A. Chess Placing(1ni)(水题)(div.2)
- java算法:兔子生兔子
- 先验概率、后验概率、似然函数概念的区分
- 英语,对程序员有多重要?
- Android混淆发布依赖
- 兼容微信6.74 ios12版本
热门文章
- Python学习笔记---day02快速上手
- Nessus 安装文件和详细教程(kali系统,附网盘下载链接)
- 惠普HP Deskjet Ink Advantage 3540 打印机驱动
- 华为mate40pro+和华为p40pro+哪个好
- increment java_Java中的increment()有什么作用?
- 在m1/m2芯片的mac电脑上运行Stable Diffusion的全步骤
- AutoJs 4.1.1 实战教程、Hamibot
- matlab趣味程序,小学生C++趣味编程 PDF 全资料版
- 启动mysql 数据库服务器_启动及关闭MySQL服务器的正确方式
- 【阿里巴巴】数据开发暑期实习生面试面经 技术面 已凉凉