== 软件项目 ==
160KM PIS服务器git仓库主页: https://git.g77k.com/qichunren/ntpis160
PIS服务器软件ntpis160有两个分支,分支1.x是以在与四方所PIS统型(2017-9)之前基于25t的界面风格和需要开发的,软件的运行环境是XUbuntu 14.04;分支master是目前正在应用的,按照四方所PIS界面和操作需求,在1.x分支后续开发的,软件的运行环境是ARM 335x,使用BuildRoot构建而成的嵌入式Linux系统 [https://git.g77k.com/yiling.cao/pudge-buildroot/tree/160km-pis-server 160km-pis-server]。
== PIS Server 1.x ==
[[160KM PIS车厢控制器项目]]的git仓库主页: https://git.g77k.com/qichunren/ntpis160-cabin-controller ,这个项目是用于在与四方所通型之前的,运行在ARM 335x系统上的,现在已经不再使用,使用了新的STM32平台的车厢控制器。
操作系统: Ubuntu 16.04,使用了overlayfs使得非/home都是只读模式。如果涉及到的操作(如apt安装软件,修改系统配置等)需要改动非/home/目录的文件读写,需要先进去读写模式,然后再操作。
* 程序目录:/home/novotech/app/
* 日志目录:/home/novotech/ntpis160_logs/
* 程序自启动脚本:/home/novotech/.config/autostart/ntpis160.desktop
* 程序启动脚本:ntpis160.start
* 程序停止脚本:ntpis160.stop
== PIS Server ==
服务器IP是192.168.9.200,子网掩码是255.255.0.0,可以通过ssh远程登录,用户名是root,密码是novote.ch
串口外设:
* FM & TEMP Sensor: /dev/ttyS4
* GPS: /dev/ttyACM0
* TOUCH Screen: /dev/ttyS3
* 160KM列车车厢LED屏控制器设备名称: /dev/ttyS2
* TCMS设备名称: /dev/ttyS1
车内屏和车外屏的协议有旧的25T版本和新版本协议。
25T版本的LED屏协议在这里:[[1.帆兴交通设备车号屏通讯协议]]
TCMS与PIS之间的协议见《时速160公里集中动力动车组PIS与TCMS通信协议.doc》文档。
== 系统维护 ==
[[校正160KM PIS主机触摸屏]]
[[160公里车厢控制器更新]]
[[160公里PIS数据包更新]]
[[160KM PIS主机软件更新]]
[[160KM PIS常见问题]]
=== 系统备份 ===
在进行系统备份时,不需要将整个硬盘备份,通过parted工具查看分区end在哪里,然后dd备份。
sudo dd if=/dev/sdc bs=1G count=27 | gzip > /home/qichunren/img/ntpis160km-2017-06-21.img.gz
=== 系统恢复 ===
在有了dd备份的系统img后,可以通过dd恢复到整个硬盘中:
gunzip -c /home/qichunren/img/ntpis160km-2017-06-21.img.gz | sudo dd of=/dev/sdc bs=16M
== LED屏控制卡 ==
*控制卡ID说明:1111,车内信息显示屏;0111,车内车号屏;1011,车外屏上半部分,0011,车外屏下半部分。
== 160KM 机箱内部板卡通讯协议 ==
=== CPU 与 FM板卡通讯协议 ===
====物理层协议====
*通过串口通讯,9600波特率,校验位无,数据位8位,停止位1位
=====帧格式表=====
{| class="wikitable sortable"
|-
! 起始位 !! 数据位 !! 校验位置 !! 结束位置
|-
|0xA5,一个字节长度||见数据位表,变长||数据位(从数据位开始到数据位结束)的CRC校验,2个字节长度,低位在前,高位在后||0x5A,一个字节长度
|}
=====数据位表=====
{| class="wikitable sortable"
|-
! 数据来源地址 !! 目的地址 !! 帧序号 !! 数据长度 (第5-6位) !! 数据命令以及数据内容
|-
|0x01表示第一块CPU板,0x02表示第二块CPU板,0x03表示第三块CPU板,'''目前只有一块335X CPU 板子,只用到0x01''';
'''0x81表示FM板子,0x82表示温度传感器板子''',一个字节||0x01表示第一块CPU板,0x02表示第二块CPU板,0x03表示第三块CPU板'''目前只有一块335X CPU 板子,只用到0x01''';
0x81表示FM板子,0x82表示第二块温度传感器板子''';
0x80表示目的地址是广播给所有的CPU电路板,0xfe表示目的地址是所有的STM32电路板,0xff表示广播给系统中所有设备,其他地址备用,一个字节长度||主动发送数据设备没发送一次数据加一个,两个字节,低位在前,高位在后(大于0xffff,清零),接收需要返回数据同数据返回||数据命令以及数据内容部分数据长度,两个字节,低位在前,高位在后||见数据命令以及数据内容表,变长
|}
=====数据命令以及数据内容表=====
{| class="wikitable sortable"
|-
! 命令序号(定长,两个字节低位在前,高位在后),第7-8位 !! 命令内容(变长,0到n个字节),第9位开始 !! 是否需要回复(定长,1个字节)
|-
|1,335X读取STM32软件版本||无||1表示需要返回
|-
|2,STM32应答上传软件版本||例如,"S160FM_17103001",15个字节长度||0表示无需返回
|-
|3,335X读取STM32硬件版本||数据长度0|1表示需要返回
|-
|4,STM32应答上传硬件版本||例如,"H160FM_NT1733A1",15个字节长度||0表示无需返回
|-
|5,STM32主动上传软件版本||例如,"S160FM_17103001",15个字节长度||0表示无需返回
|-
|6,335x应答||0表示正常,1表示错误||0表示无需返回
|-
|7,STM32主动上传硬件版本||例如,"H160FM_NT1733A1",15个字节长度||0表示无需返回
|-
|8,335x应答||0表示正常,1表示错误||0表示无需返回
|-
|9,335X下达FM收台命令||0xXX(收台信噪比设置,FM板子上默认值是4,设定范围是1-30,其他无效),0xXX(收台信号强度设置,FM板子默认值是30,设定范围是10 - 70,其他无效),一共两个字节||1表示需要返回
|-
|10,STM32 收到收台命令||0表示正常,1表示错误。(收到此命令,且命令正确后,STM32进入收台模式,收台时间需要持续30S左右,在收台过程中,不会响应335x任何命令)||0表示无需返回
|-
|11,STM32发送收台结束后,主动上报收台结果命令||0xXX(0x00,表示FM模块正常,其他表示FM故障),0xXX,一个字节表示找到的电台数量,'''0xXX,0xXX,两个字节,表示电台1的频率,0xXX,电台1信号强度''';'''0xXX,0xXX,两个字节,表示电台2的频率,0xXX,电台1信号强度''',依次....||1表示需要返回
|-
|12,335x应答||0表示正常,1表示错误||0表示无需返回
|-
|13,335X下达设置FM声音命令||0xXX,一个字节,0 - 63有效||1表示需要返回
|-
|14,STM32 收到设置FM声音命令||0表示正常,1表示错误。并设置FM声音||0表示无需返回
|-
|15,335X下达设置音源选择命令||0xXX,一个字节,0表示FM音源,'''1表示外接音源并打开外接音源,2表示选择外接音源并关闭外接音源''',其他无效||1表示需要返回
|-
|16,STM32 设置音源选择命令||0表示正常,1表示错误。并设置音源||0表示无需返回
|-
|17,335X下达获取FM电台信息命令||无||1表示需要返回
|-
|18,STM32上报收台结果命令||0xXX(0x00,表示FM模块正常,其他表示FM故障),0xXX,一个字节表示找到的电台数量,'''0xXX,0xXX,低在前,高在后,两个字节,表示电台1的频率,0xXX,电台1信号强度''';'''0xXX,0xXX,两个字节,表示电台2的频率,0xXX,电台1信号强度''',依次....||0表示需要返回
|-
|19,335X下达电台设置命令||0xXX,0xXX,低在前,高在后,两个字节||1表示需要返回
|-
|20,STM32应答||0表示正常,1表示错误(收到正确数据后,FM调频相应频率)||0表示无需返回
|}
=== CPU 与 温度板卡通讯协议 ===
====物理层协议====
*通过串口通讯,9600波特率,校验位无,数据位8位,停止位1位
=====帧格式表=====
{| class="wikitable sortable"
|-
! 起始位 !! 数据位 !! 校验位置 !! 结束位置
|-
|0xA5,一个字节长度||见数据位表,变长||数据位(从数据位开始到数据位结束)的CRC校验,2个字节长度,低位在前,高位在后||0x5A,一个字节长度
|}
=====数据位表=====
{| class="wikitable sortable"
|-
! 数据来源地址 !! 目的地址 !! 帧序号 !! 数据长度 (第5-6位) !! 数据命令以及数据内容
|-
|0x01表示第一块CPU板,0x02表示第二块CPU板,0x03表示第三块CPU板,'''目前只有一块335X CPU 板子,只用到0x01''';
'''0x81表示FM板子,0x82表示温度传感器板子''',一个字节||0x01表示第一块CPU板,0x02表示第二块CPU板,0x03表示第三块CPU板'''目前只有一块335X CPU 板子,只用到0x01''';
0x81表示FM板子,0x82表示第二块温度传感器板子''';
0x80表示目的地址是广播给所有的CPU电路板,0xfe表示目的地址是所有的STM32电路板,0xff表示广播给系统中所有设备,其他地址备用,一个字节长度||主动发送数据设备没发送一次数据加一个,两个字节,低位在前,高位在后(大于0xffff,清零),接收需要返回数据同数据返回||数据命令以及数据内容部分数据长度,两个字节,低位在前,高位在后||见数据命令以及数据内容表,变长
|}
=====数据命令以及数据内容表=====
{| class="wikitable sortable"
|-
! 命令序号(定长,两个字节低位在前,高位在后),第7-8位 !! 命令内容(变长,0到n个字节),第9位开始 !! 是否需要回复(定长,1个字节)
|-
|1,335X读取STM32软件版本||无||1表示需要返回
|-
|2,STM32应答上传软件版本||例如,"S160TE_17103001",15个字节长度||0表示无需返回
|-
|3,335X读取STM32硬件版本||数据长度0|1表示需要返回
|-
|4,STM32应答上传硬件版本||例如,"H160TE_NT1734A1",15个字节长度||0表示无需返回
|-
|5,STM32主动上传软件版本||例如,"S160TE_17103001",15个字节长度||0表示无需返回,1表示无需返回
|-
|6,335x应答||0表示正常,1表示错误||0表示无需返回
|-
|7,STM32主动上传硬件版本||例如,"H160TE_NT1734A1",15个字节长度||0表示无需返回,1表示无需返回
|-
|8,335x应答||0表示正常,1表示错误||0表示无需返回
|-
|9,STM32主动上传温度||0xXX,0xXX,温度ADC值(低位在前,高位在后),0xXX,0xXX,温度ADC校正值(详见'''温度ADC校正值说明'''),0xXX,0xXX,上传温度值(低位在前,高位在后,温度为:(温度值 - 60),比如上传温度值为91 ,则实际温度为(91 - 60 = 31摄氏度),0xXX,表示传感器状态(0x00,传感器OK,0x01,传感器故障)||0表示无需返回,1表示无需返回
|-
|10,335x应答||0表示正常,1表示错误||0表示无需返回
|-
|11,335X设置传感器ADC校正值||0xXX,0xXX,温度ADC校正值(详见'''温度ADC校正值说明''')||1表示需要返回
|-
|12,STM32应答||一个长度,0x00表示数据正常,其他表示数据异常||0表示无需返回
|}
=====温度ADC校正值=====
'''数据说明:在1000欧姆时(精密电阻1000欧姆档,或恒温槽0度时,精密PT1000),下位机(stm32)上传温度AD采集原始值与1000欧姆时AD标准值(标准AD值为 :2048)的差值,如果下位机上传的 是 2058,差值为 2048 - 2065 = -17,则上位机发送的相应通道的校正AD值为:0x111 (其中,第一个1表示 实际值比标准值大,后面0x11 即为 17),如果下位机上传的 是 1731,差值为 2048 - 1976 = 72,则上位机发送的相应通道的校正AD值为:0x048 (其中,第一个0表示 实际值比标准值小,后面0x48 即为72),如果 误差值 大于 255,则认为硬件有故障,不可校正,同时下位机如果收到校正值大于0x1ff,认为不是校正值,不予处理。低位在前,高位在后'''
=== PIS主控站 与 车厢控制器通讯协议(车厢控制器code升级部分) ===
=====数据命令以及数据内容表=====
{| class="wikitable sortable"
|-
! 主控站ID(定长,1个字节 !! 车厢控制器ID(定长,1个字节 !! 命令序号(定长,1个字节 ) !! 命令内容(变长,0到n个字节)
|-
|0x81,不变||同车厢所在车厢号||1,主控站获取车厢控制器软件版本号||无
|-
|0x81,不变||同车厢所在车厢号||2,STM32应答||例如,"LJTCC1710182",12个字节长度
|-
|0x81,不变||同车厢所在车厢号||3,PIS主机提出升级||无
|-
|0x81,不变||同车厢所在车厢号||4,STM32应答||0,数据正常,1,数据错误
|-
|0x81,不变||同车厢所在车厢号||5,PIS主机发送代码数据长度给STM32||4个字节长度,低位在前,高位在后
|-
|0x81,不变||同车厢所在车厢号||6,STM32应答||0,数据正常,1,数据错误
|-
|0x81,不变||同车厢所在车厢号||7,PIS主机发送代码数据给STM32||'''见PIS发送代码数据给STM32数据内容表'''
|-
|0x81,不变||同车厢所在车厢号||8,STM32应答||0xXXXX,代码包序号,低位在前,高位在后),0xXX(0,数据正常,1,数据错误),一共3个字节
|-
|0x81,不变||同车厢所在车厢号||9,PIS主机发送传输数据完毕命令||无
|-
|0x81,不变||同车厢所在车厢号||10,STM32应答||0,数据正常,1,数据错误
|-
|0x81,不变||同车厢所在车厢号||11,PIS主机发送强行结束升级命令||无
|-
|0x81,不变||同车厢所在车厢号||12,STM32应答||0,数据正常,1,数据错误
|}
=====车厢控制器返回主控站LED屏控制卡软件版本号(使用显示信息命令0x02)=====
{| class="wikitable sortable"
|-
! 主控站ID(定长,1个字节 !! 车厢控制器ID(定长,1个字节 !! 命令序号(定长,1个字节 ) !! 命令内容(变长,0到n个字节)
|-
|0x81,不变||同车厢所在车厢号||0x01,表示反馈LED控制卡软件版本号||每个STM32软件版本号字长8个字节,每个版本号之间使用''','''隔开,一共16个STM32软件版本,总字节长度是144,软件版本依次为:ID1车外屏上部分,ID1车外屏下部分,ID2车外屏上部分,ID2车外屏下部分,ID3车外屏上部分,ID3车外屏下部分,ID4车外屏上部分,ID4车外屏下部分,ID8坐车车内信息显示屏,ID8坐车车内车号屏,ID9坐车车内信息显示屏,ID9坐车车内车号屏,ID5窝车车内信息显示屏,ID5窝车车内车号屏,ID6窝车车内信息显示屏,ID6窝车车内车号屏
|}
=====PIS发送代码数据给STM32数据内容表=====
{| class="wikitable sortable"
|-
! 代码包序号 !! 代码数据 !! 校验
|-
|0x0001,两个字节,低位在前,表示第一包数据,依次递增||代码数据,128个字节,不够128字节补充0xff||代码数据crc16校验,2个字节,低位在前,高位在后
|}
=== PIS主控站 与 车厢控制器通讯协议(设置车厢内外屏亮度命令) ===
=====设置亮度命令=====
{| class="wikitable sortable"
|-
! SXT (4个字节)!!Length HIGH, Length HIGH(两个字节)!! CMD(1个字节)!! Device TYPE(1个字节)!!Device ID(1个字节)!!亮度(1个字节)
|-
! 77 FF AA 09!!0x00 0x01!! 0x56(表示设置屏亮度命令)!!屏类型!!屏地址!!亮度,1-9有效,其他无效
|-
|}
=====设置清除屏保存数据mil=====
{| class="wikitable sortable"
|-
! SXT (4个字节)!!Length HIGH, Length HIGH(两个字节)!! CMD(1个字节)!! Device TYPE(1个字节)!!Device ID(1个字节)!!清除保存数据区域(1个字节)
|-
! 77 FF AA 09!!0x00 0x01!! 0x3d(表示设置屏亮度命令)!!屏类型!!屏地址!!显示区域
|-
|}
=====设置显示模式命令=====
{| class="wikitable sortable"
|-
! SXT (4个字节)!!Length HIGH, Length HIGH(两个字节)!! CMD(1个字节)!! Device TYPE(1个字节)!!Device ID(1个字节)!!亮度(1个字节)
|-
! 77 FF AA 09!!0x00 0x01!! 0x58(表示设置显示模式命令)!!屏类型!!屏地址!!1,表示立即更新显示,2,表示滚动完毕更新显示,其他无效
|-
|}
|}
=== 车外屏ID设置命令 ===
CMD:0x59;Display mode:第一个字节当前ID(0到99,或者0xff,所有的都设置),第二个字节设置新的ID(0到99,或者0xff(恢复为硬件ID)),第三个字节选择已经设置ID是否可以再设置(0不设置,1设置)
==PIS 160KM字库(字库扫描方式都是从上到下,从左到右)==
*制作字库24点阵ASC字库,24点阵汉子字库(不带全角标点符号),24点阵汉字全角标点符号;
**24点阵ASC字库,生成字库文件名为'''ASC24''',每一个字符点个数是24*12个点,占字库空间大小是24*16/8 = 48个字节,前面36个字节有效,后面12个字节填0x00,字符字库在文件中的存储位置是:ch*48,比如说:字符A(0x41),在文件 ASC24 中位置是 65*48 = 3120处开始存储
**24点阵汉子字库(不带全角标点符号),生成字库文件名为'''HZK24S''',每一个汉字字模点个数为24*24个点,占字库空间大小是24*24/8 = 72个字节。字符在字库文件中的存储位置是:
'''L = (*unicode & 0x00FF)-0xA0;H = ((*unicode & 0xFF00)>>8)-0xA0; P(位置) = ((L - 1 - 15) * 94 + (H - 1)) * 72'''
**24点阵汉字全角标点符号,生产字库文件名为'''HZK24T''',每一个符号字模点个数为24*24个点,占字库空间大小是24*24/8 = 72个字节。字符在字库文件中的存储位置是:
'''L = (*unicode & 0x00FF)-0xA0;H = ((*unicode & 0xFF00)>>8)-0xA0; P(位置) = L = ((L - 1) * 94 + (H - 1)) * 72; '''
*制作32点阵ASC字库,32点阵汉子字库(包含全角标点符号);
**32点阵ASC字库,生成字库文件名为'''ASC32''',每一个字符点个数是32*16个点,占字库空间大小是32*16/8 = 64个字节,字符字库在文件中的存储位置是:ch*64,比如说:字符A(0x41),在文件 ASC24 中位置是 65*64 = 4160处开始存储
**32点阵汉子字库(带全角标点符号),生成字库文件名为'''HZK32''',每一个汉字字模点个数为32*32个点,占字库空间大小是32*32/8 = 128个字节。字符在字库文件中的存储位置是:
'''L = (*unicode & 0x00FF)-0xA0;H = ((*unicode & 0xFF00)>>8)-0xA0; P(位置) = (((L - 1) * 94 + (H - 1)) * 128'''
**制作48点阵ASC字库。生成字库文件名为'''ASC48''',每一个字符点个数是32*16个点,占字库空间大小是32*16/8 = 64个字节,字符字库在文件中的存储位置是:ch*144,比如说:字符A(0x41),在文件 ASC24 中位置是 65*144 = 9216处开始存储
==PIS160 售后维修记录==
*1、2019年1月23日,160车杭州开往北京,出现第4、3、2、1 四节车厢出现显示时有时无现象,于1月25日在杭州,断开5车厢与4车厢连接,5车厢485线正常(数据线D+,D-电压在5V左右),5车厢后485线异常(数据线D+,D-电压在0V左右),再到1车厢,断开1、2车厢485线,1车厢485线正常,1车厢后485线异常,再到2车厢检测,情况同1车厢,再到3车厢检测,断开3、4车厢线,3车厢输入485线正常,3车厢输出485线异常,判断4车厢输入信号正常,3车厢输出信号异常,断开3、2车厢连线,单测试3车厢 车厢控制器 485线信号异常,判断3车厢 车厢控制器 故障。将3车厢 车厢控制器 换为新技售后备用车厢控制器,一切现实正常。'''另注:3车厢 车厢控制器 为莱德生产'''
*2、板子上有一颗 0805 封装的 2欧姆 限流电阻故障:
造成原因:
1、车体可能会有过大干扰,引起电阻失效;
2、车上有车厢控制器出现短路等故障,导致源端(PIS主机485板)限流保护电阻失效
3、电阻单体质量原因,导致电阻失效;
预防措施:
使用过电流能力更强电阻,或者使用自恢复保险丝
==PIS160 售后管理维护==
===数据文件的备份与更新===
*备份语音文件:在U盘的根目录下创建NTPIS-ACTION.txt文件,在文件中编辑文本export_audios并保存,将U盘插入PIS主机的USB接口即可导出语音文件(*语音文件较多时,导出时间较长,在显示导出语音文件完成后再拔出U盘).
*备份数据库文件:在U盘的根目录下创建NTPIS-ACTION.txt文件,在文件中编辑文本export_db并保存,将U盘插入PIS主机的USB接口即可导出数据库文件(*在显示导出数据库文件成功后再拔出U盘).
*更新数据库文件:在U盘的根目录下创建NTPIS-UPDATE.txt文件,同时将要更新的数据库文件(**.db)放在同级目录下,将U盘插入PIS主机的USB接口,然后根据界面提示进行选择更新,PIS主机自动重启即可完成数据库更新.
*更新语音文件:
**更新单个语音文件:在U盘的根目录下创建NTPIS-UPDATE.txt文件,同时将要上传的语音文件(*.wav/*.mp3)放在同级目录下,将U盘插入PIS主机的USB接口,然后根据界面提示进行选择更新,根据更新界面显示的日志即可判断是否更新成功.
**更新多个语音文件:在U盘的根目录下创建NTPIS-UPDATE.txt文件,同时将要上传的多个语音文件进行打包(*.zip)放在同级目录下,将U盘插入PIS主机的USB接口,然后根据界面提示进行选择更新,PIS主机自动重启即可完成多个语音包更新.
'''备份与更新时标识文件不一样,标识文件不能同时存在.'''
'''更新时注意可使用的存储空间(df -h).'''
===主程序的更新===
从 http://192.168.8.29:81/aria-160km-pis-server-mk2-buildroot/ 找到 对应的 160km-pis-server-update-{日期时间戳}.tar.xz 文件,将文件下载到本地,解压,其中的 app 目录里包括了主程序和相关的所有脚本.
*单独更新主程序:只需要将新版主程序文件 ntpis160 和标识文件 NTPIS-UPDATE.txt 一同放在 U 盘根目录中即可,然后根据界面提示进行选择更新,PIS主机重启即可完成主程序更新.
*更新主程序及其其它变动文件:创建一个文件夹(eg:ntpis160-update),将主程序ntpis160文件放入其中,在其中创建files文件夹(将要变动的文件放入其中),之后创建一个名为 post_update.sh 脚本文件(它在软件更新时会被自动执行,在这个脚本中可以编写除了更新 ntpis160 主程序以外的其它操作),将其打包为zip格式的压缩包(软件更新包);将软件更新包(*.zip)和标志文件NTPIS-UPDATE.txt放在U盘根目录下,完成更新.
'''注意查看系统版本是否变为预期版本'''
===屏幕校准===
*在U盘根目录下创建NTPIS-TOUCH.txt文件,将U盘插入PIS主机USB接口,根据提示操作即可
===查看系统运行状态===
*这些命令需要电脑与PIS主机网口建立通信,然后通过putty软件ssh进行远程登录输入查看
**fdisk -l ---查看所有磁盘存储空间
**df -h ---查看用户可以使用的存储空间(与磁盘存储总空间差距太大时可扩展)
**top ---查看当前所有进程运行的状态
**ps -ef ---查看主机所有进程