共享单车也是物联网技术的一种应用,我们在共享单车上可以看到两种技术,一是实时定位记录用户行驶里程路线等信息,二是可以通过移动网络的方式打开和关闭车锁。 那么在本节课中我们将尝试模拟制作一个简单的共享单车系统。
知识锦囊
公共交通工具的“最后一公里”是城市居民出行采用公共交通出行的主要障碍,也是建设绿色城市、低碳城市过程中面临的主要挑战。 共享单车通过在校园、地铁站点、公交站点、居民区、商业区、公共服务区等提供服务,完成交通行业最后一块“拼图”,带动居民使用其他公共交通工具的热情,与其他公共交通方式产生协同效应。 共享单车是一种分时租赁模式,也是一种新型绿色环保共享经济。
GPS模块

GPS模块是一个高性能,高度集成的多模式卫星定位和导航模块。它支持GPS /北斗/ Glonass /伽利略/ QZSS / SBAS,使其适用于GNSS定位应用,例如汽车导航,智能穿戴和无人机。
我们可以通过GPS模块来记录用户里程、路线、位置等基础信息,通过移动网络通讯的行驶来控制共享单车旋转舵机打开开关。接下来让我们看看如何制作吧!
实践操作
任务一:使用GPS模块获取实时位置
将GPS模块连接到开发板的A2/D2接口,然后编写以下程序并上传:
#include <SoftwareSerial.h>#define BAT_ENABLE 19 //Grove端口使能引脚SoftwareSerial SoftSerial(2, 3);unsigned char buffer[64]; // buffer array for data receive over serial portint count=0; // counter for buffer arrayvoid setup(){digitalWrite(BAT_ENABLE, HIGH);//启用Grove端口SoftSerial.begin(9600); // the SoftSerial baud rateSerial.begin(9600); // the Serial port of Arduino baud rate.}void loop(){if (SoftSerial.available()) // if date is coming from software serial port ==> data is coming from SoftSerial shield{while(SoftSerial.available()) // reading data into char array{buffer[count++]=SoftSerial.read(); // writing data into arrayif(count == 64)break;}Serial.write(buffer,count); // if no data transmission ends, write buffer to hardware serial portclearBufferArray(); // call clearBufferArray function to clear the stored data from the arraycount = 0; // set counter of while loop to zero}if (Serial.available()) // if data is available on hardware serial port ==> data is coming from PC or notebookSoftSerial.write(Serial.read()); // write it to the SoftSerial shield}void clearBufferArray() // function to clear buffer array{for (int i=0; i<count;i++){buffer[i]=NULL;} // clear all index of array with command NULL}
上传成功程序之后打开串口监视器将波特率设置为9600,此时你应该可以看到串口分钟有数据输出。
这些数据我们并不能直接使用,我们需要将数据导出为KML文件,然后使用谷歌地球才可以解析出详细地址。
接下来下载安装u-center软件,软件界面如图所示:
我们在菜单栏找到“Receniver”选择“Connection”连接到开发板的COM口。
注意:此时串口监视器应该关闭,否则由于串口占用无法在该软件中打开COM口!
然后在“Receniver”选择“Baudrate”选择波特率为9600。
我们可以在软件底部看到连接状态。
连接成功之后,点击菜单栏中“view”选择“Text console”打开文本显示器,这里可以看到GPS模块的情况。
如果右侧的图表没有内容代表没有搜索到GPS信号,这是因为该模块功率较小,你可以将设备移动到室外空旷的地方再次进行连接,如果成功搜索到GPS信号,那么你可以看到详细的数据输出。

当GPS模块成功收到信号之后,我们就可以将位置信息导出了,首先点击“File”选择“Database Export”选择“Google Earth KML”将位置信息保存到电脑上。
然后下载安装Google Earth软件(相关谷歌功能需要科学上网)
最后使用Google Earth打开刚刚保存的KML文件即可查询到刚才GPS所处位置。
任务二:通过移动网络远程开锁
在第8课中我们通过移动网络向OneNET服务器发送了数据,那么在本任务中我们将接收来自OneNET平台的数据来控制设备。首先将舵机连接到开发板的A2/D2引脚,将SIM卡插入开发板,然后编写程序:
#include <SerialCommand.h>#include <SoftwareSerial.h>#include <Servo.h>Servo myservo;#define BAT_ENABLE 19 //Grove端口使能引脚int newval = 32; //定义变量#if defined(ARDUINO_ARCH_AVR)#define debug Serial#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)#define debug SerialUSB#else#define debug Serial#endifint a;int b;int c;int d;int f;char e[100];char g[100];char *cur;void setup() {digitalWrite(BAT_ENABLE, HIGH);//启用Grove端口pinMode(GROVE_ENABLE,OUTPUT);digitalWrite(GROVE_ENABLE,HIGH);myservo.attach(2);//设置舵机接D2脚delay(100);SerialUSB.begin(115200);LTE.begin(115200); //Serial2Serial1.begin(115200); //Grovewhile (!Serial) {;}Serial.println("SAMD MCU Ready");pinMode(LTE_PWR,OUTPUT);pinMode(LTE_RESET,OUTPUT);pinMode(LTE_WAKEUP,OUTPUT);pinMode(LTE_ENABLE,OUTPUT);digitalWrite(LTE_PWR,HIGH);digitalWrite(LTE_RESET,LOW);digitalWrite(LTE_WAKEUP,LOW);digitalWrite(LTE_ENABLE,HIGH);Serial.println("SAMD21[1] Init OK");delay(2500);LTE.write("AT+CGACT=1,1\r\n");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("AT+CGACT=1,1\r\n");delay(2000);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("AT+MQTTCFG=\"183.230.40.39\",6002,\"728817855\",600,\"434575\",\"jQMUBpFbzSRe8dstkvMN87HXH70=\",0\r\n");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("AT+MQTTOPEN=1,1,0,0,0,,\r\n");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}LTE.write("AT+MQTTSUB=\"TEST\",1\r\n");delay(2500);while(LTE.available()){SerialUSB.write(LTE.read());}}void loop() {String ss = String(newval, DEC);char buf[256];//>>>>转字符串String buff;ss.toCharArray(buf, 9);if(SerialUSB.available()){LTE.write(SerialUSB.read());}if(LTE.available()){buff = LTE.readString();buff.toCharArray(buf, buff.length());SerialUSB.write(buf);}cur = strstr(buf, "+MQTTPUBLISH:");if(cur != NULL){sscanf(cur,"+MQTTPUBLISH: %d,%d,%d,%d,\"%[^\"]\",%d,%[^\r]",&a,&b,&c,&d,e,&f,g);if(strcmp(g, "ON") == 0){SerialUSB.println("\n");SerialUSB.println("ON!");myservo.write(0);}if(strcmp(g, "OFF") == 0){SerialUSB.println("\n");SerialUSB.println("OFF!");myservo.write(90);}delay(100);}}
该程序的逻辑是:首先通过移动网络连接到OneNET平台,然后等待接收消息;此时我们可以在OneNET平台下发命令,当开发板收到“ON”指令则将舵机转动到0度;当开发板接收到“指令”则将舵机转动到90度。
上传完成程序之后打开串口监视器,在串口监视器中查看程序运行情况:
当串口监视器中都显示ok代表服务器和网络连接成功,此时可以转到后续步骤。如果串口监视器中显示“ERRO 600”错误,那么代表初始化失败。解决办法:保持串口监视器打开的情况下,拔掉开发板的数据线然后重新接入数据线,再关闭打开串口监视器即可。
打开OneNET网站:https://open.iot.10086.cn/develop/global/product/#/console 登录之后找到我们上次登陆的设备(如果设备和账号发生改变请修改代码61行中的信息,修改方法参考第8课任务一)。
在产品服务中找到“多协议接入”选择我们在第8课中注册的设备,打开设备详情页。
然后在设备名称后方的“更多操作”栏中找到“下发命令”按钮并进入。
点击“下发命令”按钮进入编辑页,在上方选择“字符串”在下方输入“ON”然后点击“发送”
此时我们可以在设备串口监视器中看到命令已经下发成功,并且舵机转动到0度了。
接下来尝试发送一下“OFF”指令。
此时舵机已经转动到90度了。
