共享单车也是物联网技术的一种应用,我们在共享单车上可以看到两种技术,一是实时定位记录用户行驶里程路线等信息,二是可以通过移动网络的方式打开和关闭车锁。 那么在本节课中我们将尝试模拟制作一个简单的共享单车系统。

知识锦囊

公共交通工具的“最后一公里”是城市居民出行采用公共交通出行的主要障碍,也是建设绿色城市、低碳城市过程中面临的主要挑战。 共享单车通过在校园、地铁站点、公交站点、居民区、商业区、公共服务区等提供服务,完成交通行业最后一块“拼图”,带动居民使用其他公共交通工具的热情,与其他公共交通方式产生协同效应。 共享单车是一种分时租赁模式,也是一种新型绿色环保共享经济。
image.png

GPS模块

image.png
GPS模块是一个高性能,高度集成的多模式卫星定位和导航模块。它支持GPS /北斗/ Glonass /伽利略/ QZSS / SBAS,使其适用于GNSS定位应用,例如汽车导航,智能穿戴和无人机。

我们可以通过GPS模块来记录用户里程、路线、位置等基础信息,通过移动网络通讯的行驶来控制共享单车旋转舵机打开开关。接下来让我们看看如何制作吧!

实践操作

任务一:使用GPS模块获取实时位置

将GPS模块连接到开发板的A2/D2接口,然后编写以下程序并上传:
image.png

  1. #include <SoftwareSerial.h>
  2. #define BAT_ENABLE 19 //Grove端口使能引脚
  3. SoftwareSerial SoftSerial(2, 3);
  4. unsigned char buffer[64]; // buffer array for data receive over serial port
  5. int count=0; // counter for buffer array
  6. void setup()
  7. {
  8. digitalWrite(BAT_ENABLE, HIGH);//启用Grove端口
  9. SoftSerial.begin(9600); // the SoftSerial baud rate
  10. Serial.begin(9600); // the Serial port of Arduino baud rate.
  11. }
  12. void loop()
  13. {
  14. if (SoftSerial.available()) // if date is coming from software serial port ==> data is coming from SoftSerial shield
  15. {
  16. while(SoftSerial.available()) // reading data into char array
  17. {
  18. buffer[count++]=SoftSerial.read(); // writing data into array
  19. if(count == 64)break;
  20. }
  21. Serial.write(buffer,count); // if no data transmission ends, write buffer to hardware serial port
  22. clearBufferArray(); // call clearBufferArray function to clear the stored data from the array
  23. count = 0; // set counter of while loop to zero
  24. }
  25. if (Serial.available()) // if data is available on hardware serial port ==> data is coming from PC or notebook
  26. SoftSerial.write(Serial.read()); // write it to the SoftSerial shield
  27. }
  28. void clearBufferArray() // function to clear buffer array
  29. {
  30. for (int i=0; i<count;i++)
  31. {
  32. buffer[i]=NULL;
  33. } // clear all index of array with command NULL
  34. }

上传成功程序之后打开串口监视器将波特率设置为9600,此时你应该可以看到串口分钟有数据输出。
image.png
这些数据我们并不能直接使用,我们需要将数据导出为KML文件,然后使用谷歌地球才可以解析出详细地址。

接下来下载安装u-center软件,软件界面如图所示:
image.png
我们在菜单栏找到“Receniver”选择“Connection”连接到开发板的COM口。
image.png


注意:此时串口监视器应该关闭,否则由于串口占用无法在该软件中打开COM口!


然后在“Receniver”选择“Baudrate”选择波特率为9600。
image.png
我们可以在软件底部看到连接状态。
image.png
连接成功之后,点击菜单栏中“view”选择“Text console”打开文本显示器,这里可以看到GPS模块的情况。

如果右侧的图表没有内容代表没有搜索到GPS信号,这是因为该模块功率较小,你可以将设备移动到室外空旷的地方再次进行连接,如果成功搜索到GPS信号,那么你可以看到详细的数据输出。
image.png
image.png
当GPS模块成功收到信号之后,我们就可以将位置信息导出了,首先点击“File”选择“Database Export”选择“Google Earth KML”将位置信息保存到电脑上。
image.png
然后下载安装Google Earth软件(相关谷歌功能需要科学上网)

最后使用Google Earth打开刚刚保存的KML文件即可查询到刚才GPS所处位置。
image.png

任务二:通过移动网络远程开锁

在第8课中我们通过移动网络向OneNET服务器发送了数据,那么在本任务中我们将接收来自OneNET平台的数据来控制设备。首先将舵机连接到开发板的A2/D2引脚,将SIM卡插入开发板,然后编写程序:
image.png

  1. #include <SerialCommand.h>
  2. #include <SoftwareSerial.h>
  3. #include <Servo.h>
  4. Servo myservo;
  5. #define BAT_ENABLE 19 //Grove端口使能引脚
  6. int newval = 32; //定义变量
  7. #if defined(ARDUINO_ARCH_AVR)
  8. #define debug Serial
  9. #elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
  10. #define debug SerialUSB
  11. #else
  12. #define debug Serial
  13. #endif
  14. int a;
  15. int b;
  16. int c;
  17. int d;
  18. int f;
  19. char e[100];
  20. char g[100];
  21. char *cur;
  22. void setup() {
  23. digitalWrite(BAT_ENABLE, HIGH);//启用Grove端口
  24. pinMode(GROVE_ENABLE,OUTPUT);
  25. digitalWrite(GROVE_ENABLE,HIGH);
  26. myservo.attach(2);//设置舵机接D2脚
  27. delay(100);
  28. SerialUSB.begin(115200);
  29. LTE.begin(115200); //Serial2
  30. Serial1.begin(115200); //Grove
  31. while (!Serial) {
  32. ;
  33. }
  34. Serial.println("SAMD MCU Ready");
  35. pinMode(LTE_PWR,OUTPUT);
  36. pinMode(LTE_RESET,OUTPUT);
  37. pinMode(LTE_WAKEUP,OUTPUT);
  38. pinMode(LTE_ENABLE,OUTPUT);
  39. digitalWrite(LTE_PWR,HIGH);
  40. digitalWrite(LTE_RESET,LOW);
  41. digitalWrite(LTE_WAKEUP,LOW);
  42. digitalWrite(LTE_ENABLE,HIGH);
  43. Serial.println("SAMD21[1] Init OK");
  44. delay(2500);
  45. LTE.write("AT+CGACT=1,1\r\n");
  46. delay(2500);
  47. while(LTE.available()){
  48. SerialUSB.write(LTE.read());
  49. }
  50. LTE.write("AT+CGACT=1,1\r\n");
  51. delay(2000);
  52. while(LTE.available()){
  53. SerialUSB.write(LTE.read());
  54. }
  55. LTE.write("AT+MQTTCFG=\"183.230.40.39\",6002,\"728817855\",600,\"434575\",\"jQMUBpFbzSRe8dstkvMN87HXH70=\",0\r\n");
  56. delay(2500);
  57. while(LTE.available()){
  58. SerialUSB.write(LTE.read());
  59. }
  60. LTE.write("AT+MQTTOPEN=1,1,0,0,0,,\r\n");
  61. delay(2500);
  62. while(LTE.available()){
  63. SerialUSB.write(LTE.read());
  64. }
  65. LTE.write("AT+MQTTSUB=\"TEST\",1\r\n");
  66. delay(2500);
  67. while(LTE.available()){
  68. SerialUSB.write(LTE.read());
  69. }
  70. }
  71. void loop() {
  72. String ss = String(newval, DEC);
  73. char buf[256];//>>>>转字符串
  74. String buff;
  75. ss.toCharArray(buf, 9);
  76. if(SerialUSB.available()){
  77. LTE.write(SerialUSB.read());
  78. }
  79. if(LTE.available()){
  80. buff = LTE.readString();
  81. buff.toCharArray(buf, buff.length());
  82. SerialUSB.write(buf);
  83. }
  84. cur = strstr(buf, "+MQTTPUBLISH:");
  85. if(cur != NULL)
  86. {
  87. sscanf(cur,"+MQTTPUBLISH: %d,%d,%d,%d,\"%[^\"]\",%d,%[^\r]",&a,&b,&c,&d,e,&f,g);
  88. if(strcmp(g, "ON") == 0){
  89. SerialUSB.println("\n");
  90. SerialUSB.println("ON!");
  91. myservo.write(0);
  92. }
  93. if(strcmp(g, "OFF") == 0){
  94. SerialUSB.println("\n");
  95. SerialUSB.println("OFF!");
  96. myservo.write(90);
  97. }
  98. delay(100);
  99. }
  100. }

该程序的逻辑是:首先通过移动网络连接到OneNET平台,然后等待接收消息;此时我们可以在OneNET平台下发命令,当开发板收到“ON”指令则将舵机转动到0度;当开发板接收到“指令”则将舵机转动到90度。

上传完成程序之后打开串口监视器,在串口监视器中查看程序运行情况:

当串口监视器中都显示ok代表服务器和网络连接成功,此时可以转到后续步骤。如果串口监视器中显示“ERRO 600”错误,那么代表初始化失败。解决办法:保持串口监视器打开的情况下,拔掉开发板的数据线然后重新接入数据线,再关闭打开串口监视器即可。
image.png
打开OneNET网站:https://open.iot.10086.cn/develop/global/product/#/console 登录之后找到我们上次登陆的设备(如果设备和账号发生改变请修改代码61行中的信息,修改方法参考第8课任务一)。
image.png
在产品服务中找到“多协议接入”选择我们在第8课中注册的设备,打开设备详情页。
image.png
然后在设备名称后方的“更多操作”栏中找到“下发命令”按钮并进入。
image.png
点击“下发命令”按钮进入编辑页,在上方选择“字符串”在下方输入“ON”然后点击“发送”
image.png
此时我们可以在设备串口监视器中看到命令已经下发成功,并且舵机转动到0度了。
image.png
接下来尝试发送一下“OFF”指令。
image.png
此时舵机已经转动到90度了。