基本思路: 物体速度 = 两点的坐标差 / 定位时间差
也就是说,按照1Hz的频率采集GPS数据,就能算出物体运动速度
一、硬件结构
- Arduino UNO
- EC20 USB DongleA(GNSS)模块
具有4G和GPS功能
如图按照TX->RX,RX->TX,GND->GND,5V->5V接线即可
二、方案验证
EC20模块USB接口连接PC,可以看到三个串口:AT port用于发送AT指令,NMEA
port用于接收GNSS数据。但我们最终需要连接MCU使用,所以这里要测试串口,此串口引出的是AT功能。
1.GPS功能验证步骤
- 因为使用了UART,所以配置数据输出到串口:
AT+QGPSCFG="outport","uartdebug"
,另外两种为输出到USB或无输出 - 使能GPS功能
AT+QGPS=1
- 将NMEA数据输出到AT口
AT+QGPSCFG="nmeasrc",1
- 输出NMEA中GGA这条数据
AT+QGPSGNMEA="GGA"
$GPGGA,,,,,,0,,,,,,,,*66
中无有效数据是因为在室内没有GPS信号,可以按照GPGGA标准格式解析出定位、海拔高等信息。
2.GPRS功能验证步骤
(1)使用GPRS功能的目的是连接服务器,发送数据,看一下官方文档TCP部分
(2) 按照上图顺序发送AT指令
(3)串口助手输出如下:
(4) 服务器收到的16进制ASCII码消息如下:
3.至此,我们PC与EC20模块UART的通信验证完成,接下来我们可以用MCU代替PC了,逻辑如下:
三、编程实现
1.设备(MCU+EC20)与服务器间tcp通信
(1)代码实现
#include <SoftwareSerial.h>
SoftwareSerial ATserial(12, 13);//RX,TX 创建模拟串口
enum{
CPIN=0,
COPS,
CREG,
CGREG,
QICSGP,
QIACT,
QIOPEN
}AT;
void setup()
{
delay(5000);
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
Serial.begin(115200);
while (!Serial) {}
Serial.println("serial ok!");
ATserial.begin(115200);
while (!ATserial) {}
Serial.println("ATserial ok!");
ATserial.listen();
ATserial.println("AT");
delay(300);
if(ATserial.find("OK")){
Serial.println("EC20 is ready!");
}
clear_serial();
AT = CPIN;
switch(AT)//状态机
{
case CPIN:
cpin();
case COPS:
cops();
case CREG:
creg();
case CGREG:
cgreg();
case QICSGP:
qicsgp();
case QIACT:
qiact();
case QIOPEN:
qiopen();
break;
default:
break;
}
}
void loop() {
at_send();//发送测试数据
}
void cpin()
{
ATserial.println("AT+CPIN?");
delay(300);
if(ATserial.find("OK")){
Serial.println("AT+CPIN,ok");
AT = COPS;
}
clear_serial();
}
void cops()
{
ATserial.println("AT+COPS?");
delay(500);
if(ATserial.find("OK")){
Serial.println("AT+COPS,ok");
AT = CREG;
}
clear_serial();
}
void creg()
{
ATserial.println("AT+CREG?");
delay(300);
if(ATserial.find("OK")){
Serial.println("AT+CREG,ok");
AT = CGREG;
}
clear_serial();
}
void cgreg()
{
ATserial.println("AT+CGREG?");
delay(300);
if(ATserial.find("OK")){
Serial.println("AT+CGREG,ok");
AT = QICSGP;
}
clear_serial();
}
void qicsgp()
{
ATserial.println("AT+QICSGP=1,1,\"CMNET\",\"\",\"\",1");
delay(300);
if(ATserial.find("OK")){
Serial.println("AT+QICSGP,ok");
AT = QIACT;
}
clear_serial();
}
void qiact()
{
ATserial.println("AT+QIDEACT=1");
delay(300);
clear_serial();
ATserial.println("AT+QIACT=1");
delay(300);
if(ATserial.find("OK")){
Serial.println("AT+QIACT,ok");
AT = QIOPEN;
}
clear_serial();
}
void qiopen()
{
ATserial.println("AT+QIOPEN=1,0,\"TCP\",\"180.97.81.180\",54501,0,0");
delay(1000);
if(ATserial.find("OK")){
Serial.println("AT+QIOPEN,ok");
}
clear_serial();
}
void at_send()
{
ATserial.println("AT+QISENDEX=0,\"3132333435\"");
delay(1000);
if(ATserial.find("OK")){
Serial.println("AT+QISENDEX,ok");
}
clear_serial();
}
void clear_serial()//清除串口缓存,否则每次都能检测到"OK"
{
while(ATserial.read() >= 0){}
while(Serial.read() >= 0){}
}
(2)Arduino串口监控器输出LOG如下
(3)TCP服务器收到数据
2.发送GPS数据
(1)代码实现
模块gps功能初始化函数,在setup()中调用
void gps_init()
{
//AT+QGPSCFG="outport","uartdebug"
//AT+QGPS=1
//AT+QGPSCFG="nmeasrc",1
ATserial.println("AT+QGPSCFG=\"outport\",\"uartdebug\"");
delay(300);
if(ATserial.find("OK")){
Serial.println("AT+QGPSCFG_outport,ok");
}
clear_serial();
ATserial.println("AT+QGPS=1");
delay(300);
if(ATserial.find("OK")){
Serial.println("AT+QGPS,ok");
}
clear_serial();
ATserial.println("AT+QGPSCFG=\"nmeasrc\",1");
delay(300);
if(ATserial.find("OK")){
Serial.println("AT+QGPSCFG_nmeasrc,ok");
}
clear_serial();
}
定位获取和发送写在loop()中
void loop(){
clear_serial();
ATserial.println("AT+QGPSGNMEA=\"GGA\"");
delay(300);
if(ATserial.find("GGA")){
String comdata = "";//缓存清零
Serial.println("GPGGA消息:
while (ATserial.available() > 0)//循环串口是否有数据
{
comdata += char(ATserial.read());//叠加数据到comdata
delay(4);//延时等待响应
}
Serial.println(comdata);
ATserial.println("AT+QISWTMD=0,2");
delay(300);
if(ATserial.find("CONNECT")){
Serial.println("++++++++进入透传模式++++++++++");
clear_serial();
ATserial.println(comdata);
delay(300);
if(ATserial.find("OK")){
Serial.println("send,ok");
}
}
}
delay(1000);
ATserial.print("+++");//退出透传模式
delay(1000);
}
(2)Arduino监控串口输出
(3)服务器接收到GNSS数据,到这里基本功能就完成了
可以透传到服务器供后端解析,也可以在本地解析通过经纬度和时间戳计算设备速度(v=s/t),这个很简单就不展开了
3.说明
(1)这里只是一个测试mode,理论可行,但与事实相去甚远(实际项目已采用其他方案)
(2)理论上2G或者NB更便宜,但是没有采用,因为在2G的频段,由于多普勒效应,如果物体高速运动,2G会发生频移,导致信号很差,丢包严重,谨记