『瀚思彼岸』» 智能家居技术论坛

标题: 小白教小白-用大夏龙雀CT511N-A模块自制车载gps [打印本页]

作者: lione95678    时间: 2024-11-19 10:53
标题: 小白教小白-用大夏龙雀CT511N-A模块自制车载gps
本帖最后由 lione95678 于 2024-11-19 11:10 编辑

  起因:最早只是想买一个4g串口透传模块,后来看到大夏龙雀的CT511N-A模块,新手套餐价格19.9,还包1年360m的流量(每月30m),想想干脆做一个车载gps也不错,放在老爷子的车上,也就有了这篇内容。
  说明:车载端使用大夏龙雀CT511N-A模块,搭配stc8g1k08a单片机使用,服务器端使用traccar和mqtt搭配node-red的mqtt接收和http get使用。
  原理:大夏龙雀CT511N-A模块在设置好gps后,大概会以每秒1次的频率通过串口发送gps信息,通过stc8g1k08a单片机的串口接收这些数据,刷选出我们需要的,然后串口发送给大夏龙雀CT511N-A模块,让大夏龙雀CT511N-A模块通过mqtt的方式发送给mqtt服务器,nod-red的mqtt接收到这些数据后发送给traccar服务端。注意,这里你自己的mqtt服务器必须是可以外网连接到的。(其实可以直接通过大夏龙雀CT511N-A模块的http get方式连接到traccar服务器,但是我这里没有使用,我是小白。另外,好像看到帖子说mqtt方式也可以直接连接traccar服务器)
硬件连接方面:买到的CT511N-A模块有6个引脚,我是用了其中4个,即vcc、gnd、rx、tx,将vcc、gnd连接到stc8g1k08a的vcc、gnd后,连接到外部5v电源(车载的话搞一个12v转5v的降压模块),CT511N-A的rx连接stc8g1k08a的tx,CT511N-A的tx连接stc8g1k08a的rx,最基本的硬件连接这样就可以了。后续考究点的,可以使用嘉立创打板后连接,我是偷懒了,又急着用,就直接用一块SOP8贴片转DIP直插的转接板焊接stc8g1k08a,然后用切了一小块洞洞板,用排母连接。  这里我提供了stc8g1k08a单片机的相关文件,你将文件解压缩,然后需要使用Keil打开gps.uvproj文件后,修改main文件的第63、65、69、185行的内容,修改成你自己的mqtt服务器地址和mqtt-topic等,然后编译下载到stc8g1k08a单片机即可使用。
  关于stc8g1k08a单片机的使用,小白可以看一下bilibili网站的教学视频,这里推荐一个,看了以后最基本的刷机,使用就没有什么大问题了,我这里就用了他的uart库函数,也使用了他的串口信息处理方式。https://www.bilibili.com/video/BV1gE411H7Nb?spm_id_from=333.788.videopod.sections&vd_source=cc2d0ed5f6c37d0a6598b20d7cabe37c
  稍微说一下stc8g1k08a单片机的main文件,大家可以用Keil打开gps.uvproj文件或者直接用vscode打开main.c文件。我用了官方库函数中的gpio库函数和上面视频中的库函数中的uart库函数和延时库函数。第一步:使用了库函数和定义了几个常量;第二步:主函数中,先初始化GPIO和串口,然后延时20秒,让4g模块可以收到4g信号(这一步不知道有没有必要,没有多测试),再让单片机通过发送AT命令,让4g模块打开网络,并配置mqtt信息,同时向mqtt服务器发送一条信息,表明4g-gps模块已上线了。然后死循环中就是毫无意义的延时(实际上死循环中应该可以不用写内容)第三步:使用串口的中断触发,当单片机串口收到4g-gps模块的gps数据后,只选取以“$GNGGA”开头的70个字符,然后把这些数据发送给4g-gps模块,让4g-gps模块使用mqtt发送给mqtt服务器。(因为gps模块会以大概每秒一次的频率发送一大段 “$GNRMC,081906.000,A,3111.123456,N,12345.123456,E,0.042,0.00,091124,,E,A*01”、“$GNGGA$GNGGA,081906.000,3111.123456,N,12345.123456,E,1,25,0.66,17.716,M,0,M,,*60”等数据,我们需要选取所需要的数据)。
  后续配置一下node-red,使用node-red的mqttin节点,接收这些数据,再把这些数据转给traccar服务器,traccar服务器的搭建,可以看一下论坛里bg6rsh的帖子,我就是用的他的https://bbs.hassbian.com/forum.php?mod=viewthread&tid=11353&highlight=traccar
  流量方面,30m/月的流量基本够你使用了,按照现在的价格,后续流量包年,5元/年,是30m/月。7元/年,是100m/月。流量叠加包的话,是100m/月的价格1.2元。

  大夏龙雀CT511N-A模块资料下载地址:http://www.szdx-smart.com/zlxz/4Gmk/4Gmokuai/407.htmlnode-red节点:
  1. [
  2.     {
  3.         "id": "3843de2a8ce37b65",
  4.         "type": "function",
  5.         "z": "eb91aafe711c13c9",
  6.         "name": "提取经纬度等信息",
  7.         "func": "msg.zuobiao = msg.payload.split(',');\nmsg.topic1 = msg.zuobiao[0];\nmsg.time1 = msg.zuobiao[1];\nmsg.lat = msg.zuobiao[2];\nmsg.long = msg.zuobiao[4];\nvar id;\nif (msg.topic ==='gps/a88888'){\n    id = "123456";\n}\nmsg.id = id;\nreturn msg;\n//上面的'gps/a88888'要配合你单片机发送的“mqtt标题”来写\n//上面的"123456"要配合你traccar服务器中的设备id来写,这里写了什么数字,traccar添加新设备时,id号也要这么写\n",
  8.         "outputs": 1,
  9.         "timeout": 0,
  10.         "noerr": 0,
  11.         "initialize": "",
  12.         "finalize": "",
  13.         "libs": [],
  14.         "x": 750,
  15.         "y": 280,
  16.         "wires": [
  17.             [
  18.                 "71f7b33471dd5d7c"
  19.             ]
  20.         ]
  21.     },
  22.     {
  23.         "id": "5e01de19f50b84f9",
  24.         "type": "inject",
  25.         "z": "eb91aafe711c13c9",
  26.         "name": "",
  27.         "props": [
  28.             {
  29.                 "p": "payload"
  30.             },
  31.             {
  32.                 "p": "topic",
  33.                 "vt": "str"
  34.             }
  35.         ],
  36.         "repeat": "",
  37.         "crontab": "",
  38.         "once": false,
  39.         "onceDelay": 0.1,
  40.         "topic": "gps/550g08",
  41.         "payload": "$GNGGA,084213.000,3104.147644,N,12131.553192,E,1,19,0.93,-17.558,M,0,M",
  42.         "payloadType": "str",
  43.         "x": 570,
  44.         "y": 360,
  45.         "wires": [
  46.             [
  47.                 "3843de2a8ce37b65"
  48.             ]
  49.         ]
  50.     },
  51.     {
  52.         "id": "46de3ec344d01f19",
  53.         "type": "mqtt in",
  54.         "z": "eb91aafe711c13c9",
  55.         "name": "",
  56.         "topic": "gps/#",
  57.         "qos": "0",
  58.         "datatype": "auto-detect",
  59.         "broker": "",
  60.         "nl": false,
  61.         "rap": true,
  62.         "rh": 0,
  63.         "inputs": 0,
  64.         "x": 270,
  65.         "y": 280,
  66.         "wires": [
  67.             [
  68.                 "3843de2a8ce37b65",
  69.                 "62cce39ea438f052"
  70.             ]
  71.         ]
  72.     },
  73.     {
  74.         "id": "71f7b33471dd5d7c",
  75.         "type": "function",
  76.         "z": "eb91aafe711c13c9",
  77.         "name": "经纬度十进制转换",
  78.         "func": "var lat = msg.lat;\nvar long = msg.long;\nvar latd;\nvar latf;\nvar lats;\nvar longd;\nvar longf;\nvar longs;\n\nvar latitude;\nvar longitude;\n\nlatd = lat.substring(0, 2);\nlatf = lat.substring(2);\nlats = latf/60;\n\nlatitude = parseFloat(latd) + parseFloat(lats);\n\nlongd = long.substring(0, 3);\nlongf = long.substring(3);\nlongs = longf/60;\n\nlongitude = parseFloat(longd) + parseFloat(longs);\n// msg.latd = latd;\n// msg.latf = latf;\n// msg.lats = lats;\n\n// msg.longd = longd;\n// msg.longf = longf;\n// msg.longs = longs;\n\nmsg.latitude = latitude;\nmsg.longitude = longitude;\nmsg.timestamp = new Date().getTime();\nreturn msg;\n\n//这个节点的内容不需要修改",
  79.         "outputs": 1,
  80.         "timeout": 0,
  81.         "noerr": 0,
  82.         "initialize": "",
  83.         "finalize": "",
  84.         "libs": [],
  85.         "x": 990,
  86.         "y": 280,
  87.         "wires": [
  88.             [
  89.                 "f42155c1a3d97fbd"
  90.             ]
  91.         ]
  92.     },
  93.     {
  94.         "id": "f42155c1a3d97fbd",
  95.         "type": "function",
  96.         "z": "eb91aafe711c13c9",
  97.         "name": "发送给traccar",
  98.         "func": "var time = msg.timestamp;\nvar lan = msg.latitude;\nvar lon = msg.longitude;\nvar id = msg.id;\n\nvar url = "http://192.168.1.244:5055/?id="+id+"&lat="+lan+"&lon="+lon+"×tamp="+time;\n\n//global.set("token",msg.payload.token);\n//global.set("s_cookie",msg.responseCookies)\nvar _msg = {};\n_msg.url = url;\n_msg.method = "GET";\n//_msg.cookies = global.get("s_cookie")\n//_msg.payload = JSON.stringify({ \n //                       "deviceId": 12345000,\n //                       "description": "MSG",\n //                       "type": "custom",\n  //                      "attributes": {\n //                           "data":   "CETest" \n //                           }\n //                       }  )  \n//_msg.headers = {"content-type": "application/json"};\n//msg.headers["X-Requested-With"] = "XMLHttpRequest"\nreturn _msg;\n\n\n//上面http://192.168.1.244:5055要修改成你traccar服务器的地址和端口号\n",
  99.         "outputs": 1,
  100.         "timeout": "",
  101.         "noerr": 0,
  102.         "initialize": "",
  103.         "finalize": "",
  104.         "libs": [],
  105.         "x": 1200,
  106.         "y": 280,
  107.         "wires": [
  108.             [
  109.                 "749acf0987f58444"
  110.             ]
  111.         ]
  112.     },
  113.     {
  114.         "id": "749acf0987f58444",
  115.         "type": "http request",
  116.         "z": "eb91aafe711c13c9",
  117.         "name": "",
  118.         "method": "use",
  119.         "ret": "obj",
  120.         "paytoqs": "ignore",
  121.         "url": "",
  122.         "tls": "",
  123.         "proxy": "",
  124.         "authType": "",
  125.         "x": 1380,
  126.         "y": 280,
  127.         "wires": [
  128.             []
  129.         ]
  130.     },
  131.     {
  132.         "id": "62cce39ea438f052",
  133.         "type": "debug",
  134.         "z": "eb91aafe711c13c9",
  135.         "name": "debug 6",
  136.         "active": true,
  137.         "tosidebar": true,
  138.         "console": false,
  139.         "tostatus": false,
  140.         "complete": "false",
  141.         "statusVal": "",
  142.         "statusType": "auto",
  143.         "x": 360,
  144.         "y": 340,
  145.         "wires": []
  146.     },
  147.     {
  148.         "id": "52be647418a619d9",
  149.         "type": "comment",
  150.         "z": "eb91aafe711c13c9",
  151.         "name": "这里的'gps/#要配合你单片机发送的“mqtt标题”来写",
  152.         "info": "",
  153.         "x": 410,
  154.         "y": 120,
  155.         "wires": []
  156.     },
  157.     {
  158.         "id": "e98bb2f66bd8ea76",
  159.         "type": "comment",
  160.         "z": "eb91aafe711c13c9",
  161.         "name": "比如你单片机里写的mqtt标题是gps/a88888,那么这个节点就可以收到",
  162.         "info": "",
  163.         "x": 470,
  164.         "y": 160,
  165.         "wires": []
  166.     },
  167.     {
  168.         "id": "0e0953cdbfa0e7cc",
  169.         "type": "comment",
  170.         "z": "eb91aafe711c13c9",
  171.         "name": "我是为了方便后续使用多个4g-gps模块,打算统一以标题“gps/车牌号”的方式来发送mqtt信息,所以这么写的",
  172.         "info": "",
  173.         "x": 580,
  174.         "y": 200,
  175.         "wires": []
  176.     }
  177. ]
复制代码

以后你还可以添加单片机的其他功能,让这个模块扩展更多玩法,比如我后续会增加几个按键,让单片机通过外部中断的方式,发送信息开关车库门等等。看来要学学单片机的知识了,价格便宜,玩法较多。stc8g1k08a只要7毛钱。




作者: lione95678    时间: 2024-11-19 10:58
这是单片机的相关文件,解压缩后使用keil修改后重新编译
作者: lione95678    时间: 2024-11-19 10:59
这是单片机main.c文件内容
  1. /*****************************************************************************
  2. * 例程名称                 : 空工程
  3. * 说明         : 新建项目可以直接复制空工程开始编程。
  4. * 接线方式     : ---
  5. * 注意                     : ---
  6. *******************************************************************************/

  7. //--包含你要使用的头文件--//
  8. #include "config.h"          //通用配置头文件

  9. //--声明一些要使用的常量--//
  10. uchar UART2_FLAG =0;     //状态机   初始状态=0  收到第一个符合条件的字符后 =1  等待第二个符合条件的字符后 =>3 第几个数据

  11. uchar GPS_Data[90];    //接受到的完整数据
  12. unsigned char f;
  13. uchar a;






  14. /******************* IO配置函数 *******************/
  15. void        GPIO_config(void)
  16. {
  17.         GPIO_InitTypeDef        GPIO_InitStructure;                //结构定义

  18.         GPIO_InitStructure.Pin  = GPIO_Pin_2 | GPIO_Pin_3;                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
  19.         GPIO_InitStructure.Mode =GPIO_OUT_PP;        //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
  20.         GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);        //初始化
  21. }


  22. /*******************************************************************************
  23. * 函 数 名         : main
  24. * 函数功能                     : 主函数
  25. * 输    入         : 无
  26. * 输    出         : 无
  27. *******************************************************************************/
  28. void main(void)
  29. {

  30.   GPIO_config();  //gpio初始化
  31.         delay_X_ms(10);
  32.        
  33.         UART_init(1,115200,1);  //串口1初始化
  34.         delay_X_ms(10);
  35.         P32 = 1;         //这里安装了2个led,一个用作电源指示灯,当单片机启动后就亮灯,一个用作gps指示灯,每发送一次gps信息指示灯闪烁一次
  36.         P33 = 1;


  37.   for( a = 1; a < 20; a = a + 1 ) //循环20次执行等待1秒,即等待20秒
  38.         {
  39.                 delay_X_ms(1000);
  40.         }
  41.         //每隔1秒向4g模块发送以下命令,用于开启模块4g和mqtt
  42.         UART_Send_string(1,"ATE0\r\n"); //关闭gps模块的指令回显
  43.         delay_X_ms(1000);
  44.         UART_Send_string(1,"AT+QICSGP=1,2\r\n"); //配置APN,连接标识符,连接类型,访问点名称,用户名,密码(不想填写的就不用写进去,后面也一样)
  45.         delay_X_ms(1000);
  46.         UART_Send_string(1,"AT+NETOPEN\r\n");  //打开数据网络开关
  47.         delay_X_ms(1000);
  48.         UART_Send_string(1,"AT+MCONFIG=设备id,用户名,密码,0\r\n"); //填写MQTT服务器信息1、设备id,用户名,密码,遗嘱开关,遗嘱qos,保留标志,遗嘱内容,前面的内容请自行修改
  49.         delay_X_ms(1000);
  50.         UART_Send_string(1,"AT+MIPSTART=服务器地址,1883,3\r\n"); //填写MQTT服务器信息2、服务器地址,端口号,mqtt协议版本,前面的内容请自行修改
  51.         delay_X_ms(1000);
  52.         UART_Send_string(1,"AT+MCONNECT=1,60\r\n"); //连接MQTT服务器
  53.         delay_X_ms(1000);
  54.         UART_Send_string(1,"AT+MPUB=mqtt标题,0,0,mqtt内容\r\n"); //发送MQTT信息,前面的内容请自行修改
  55.         delay_X_ms(1000);
  56.         UART_Send_string(1,"AT+MGPSC=1\r\n"); //打开GPS开关
  57.         delay_X_ms(1000);
  58.        
  59.        
  60.        
  61.        
  62.        

  63.        
  64.        
  65.         while(1)
  66.         {
  67.                 delay_X_ms(1000);
  68.                 delay_X_ms(1000);
  69.                 delay_X_ms(1000);

  70.                
  71.         }
  72. }

  73. void UART1_isr(void)  //说明收到数据了
  74. {
  75.         uchar Dat = SBUF;    //读到这次的数据
  76.        
  77.         //UART_Send_byte(1,UART2_FLAG); //用串口1把串口2的数据发出来
  78.         //gps的数据示例:
  79.         //$GNGGA,081906.000,3111.123456,N,12345.123456,E,1,25,0.66,17.716,M,0,M,,*60
  80.         //$GNRMC,081906.000,A,3111.123456,N,12345.123456,E,0.042,0.00,091124,,E,A*01
  81.        
  82.         switch(UART2_FLAG)
  83.         {
  84.                 case 0:
  85.                 {
  86.                         if(Dat == 0x24)     //判断第一个字符是不是“$”
  87.                         {
  88.                                 GPS_Data[UART2_FLAG] = Dat;   //存起来
  89.                                 UART2_FLAG=1;       //状态置1
  90.                         }
  91.                         break;
  92.                 }
  93.                 case 1:
  94.                 {
  95.                         if(Dat == 0x47)    //判断第二个字符是不是“G”
  96.                         {
  97.                                 GPS_Data[UART2_FLAG] = Dat;   //存起来
  98.                                 UART2_FLAG=2;       //状态置2
  99.                         }
  100.                         else
  101.                         {
  102.                                 UART2_FLAG = 0;       //状态置0
  103.                         }
  104.                         break;
  105.                 }
  106.                 case 2:
  107.                 {
  108.                         if(Dat == 0x4E)    //判断第三个字符是不是“N”
  109.                         {
  110.                                 GPS_Data[UART2_FLAG] = Dat;   //存起来
  111.                                 UART2_FLAG=3;       //状态置2
  112.                         }
  113.                         else
  114.                         {
  115.                                 UART2_FLAG = 0;       //状态置0
  116.                         }
  117.                         break;
  118.                 }
  119.                 case 3:
  120.                 {
  121.                         if(Dat == 0x47)    //判断第四个字符是不是“G”
  122.                         {
  123.                                 GPS_Data[UART2_FLAG] = Dat;   //存起来
  124.                                 UART2_FLAG=4;       //状态置2
  125.                         }
  126.                         else
  127.                         {
  128.                                 UART2_FLAG = 0;       //状态置0
  129.                         }
  130.                         break;
  131.                 }
  132.                 case 4:
  133.                 {
  134.                         if(Dat == 0x47)    ////判断第五个字符是不是“G”
  135.                         {
  136.                                 GPS_Data[UART2_FLAG] = Dat;   //存起来
  137.                                 UART2_FLAG=5;       //状态置2
  138.                         }
  139.                         else
  140.                         {
  141.                                 UART2_FLAG = 0;       //状态置0
  142.                         }
  143.                         break;
  144.                 }
  145.                 case 5:
  146.                 {
  147.                         if(Dat == 0x41)    ////判断第六个字符是不是“A”
  148.                         {
  149.                                 GPS_Data[UART2_FLAG] = Dat;   //存起来
  150.                                 UART2_FLAG=6;       //状态置2
  151.                         }
  152.                         else
  153.                         {
  154.                                 UART2_FLAG = 0;       //状态置0
  155.                         }
  156.                         break;
  157.                 }
  158.                

  159.                 default:
  160.                 {
  161.                         GPS_Data[UART2_FLAG] = Dat;
  162.                         UART2_FLAG++;
  163.                         if(UART2_FLAG>70)  //判断终止条件,这里截取了70个字符
  164.                         {
  165.                                 UART2_FLAG = 0;       //状态置0
  166.                                 UART_Send_string(1,"AT+MPUB=mqtt标题,0,0,");//请将mqtt标题修改为你自己需要的
  167.                                 UART_Send_byte(1,0x22);
  168.                                 for( a = 0; a < 70; a = a + 1 )
  169.                                 {
  170.                                         UART_Send_byte(1,GPS_Data[a]);
  171.                                 }

  172.         UART_Send_byte(1,0x22);
  173.                     UART_Send_byte(1,0x0D);
  174.                     UART_Send_byte(1,0x0A);
  175.                                 P32 = !P32;


  176.                           }
  177.                         break;
  178.                 }
  179.         }
  180. }
复制代码

作者: wbdownn    时间: 2024-11-19 17:10
30M够用不?
作者: kjjuhfv    时间: 2024-11-19 17:11
这个难度感觉还是高了

作者: wenghy    时间: 2024-11-19 17:31
很不错啊,谢谢分享,可以搞下
作者: ryanh7    时间: 2024-11-19 18:37
模块支持二次开发的话可以省掉单片机
作者: lione95678    时间: 2024-11-21 09:43
wbdownn 发表于 2024-11-19 17:10
30M够用不?

看你怎么用了,我这老爷子前几天自驾游海南,开了2300公里,按每小时100公里的时速算,用时23小时,用了大概13m的流量
作者: lione95678    时间: 2024-11-21 09:47
ryanh7 发表于 2024-11-19 18:37
模块支持二次开发的话可以省掉单片机

这个模块使用说明里明确需要另外的mcu,都是固定死的。我一开始觉得每秒1次发送gps信息太快,问了一下客服,他说通过串口发送gps信息的频率不能修改。
作者: ryanh7    时间: 2024-11-21 10:21
对自己好点,考虑一下air780eg
作者: ryanh7    时间: 2024-11-21 10:21
对自己好点,考虑一下air780eg
作者: rz12345    时间: 2025-1-25 11:38
学习学习




欢迎光临 『瀚思彼岸』» 智能家居技术论坛 (https://bbs.hassbian.com/) Powered by Discuz! X3.5