《硬件接入》耀华XK3190-A9+地磅安卓(java)接入过程分享
最近遇到在安卓上通过串口连接地磅的需求, 基本上实现了读数和判断地磅稳定状态 , 这里分享出来实现过程以方便大家开发.我们开发用的打印机是XK3190-A9+ ,需要这个打印机参数文档的可以耀华官网下载:http://www.yaohua.com.cn/companyfile/16/
地磅是通过串口连接的,连接地磅主要参数有串口名称、波特率、一帧长度、以及是否校验,校验位等其他参数;
我这边做的参数有:串口名称、波特率、一帧长度以及通讯方式;
一、地磅参数
1、串口名称
在我安卓工控机上是已接入是RS232,命名为ttfS1和ttfS3两个串口;
RS232、TTL、COM 是不同电平和逻辑的串口,百度一下大概有常用的电平标准有TTL、CMOS、LVTTL、LVCMOS、ECL、PECL、LVPECL、RS232、RS485等,还有一些速度比较高的 LVDS、GTL、PGTL、CML、HSTL、SSTL等
2、波特率
波特率即调制速率,指的是有效数据讯号调制载波的速率,即单位时间内载波调制状态变化的次数。
XK3910-A9+支持的波特率有:600、1200、2400、4800、9600;我这里统一选择了9600
3、一帧长度
是指一次信号携带的数据长度 ,耀华是8位,其中开后1位是“=”号连接位,后面7位是数据位。
4、通讯方式
意思是说地磅跟其他机器的通讯方式,可以选择连续发数据,但不接收数据、发送一次和等待接收、连续发送8位、连续发送9位这四种;我选择的是连续发送8位。
地磅上相关参数的设置方步骤和方式:
更多设置可以去下载打印机文档.
二、配置参数
1、外设参数配置,先配置上面的默认参数
String port = “/dev/ttyS1”;//串口名字,默认ttfS1
int baudRate = 9600;//波特率,默认9600
int dateLengthPerFrame = 8;//每一帧的数据长度 ,耀华是8位
2、增加上一些本地的参数配置
int stableTimeMills = 1000;//地磅稳定时间,超过这个时间数据不曾修改则表示地磅稳定,耀华的是1秒
int receiveTimeOut = 1000;//地磅接收超时,一般地磅会毫秒内发送数据,超过这个时间则表示地磅链接失败,默认是1秒没内收到数据就表示地磅链接失败
int receiveTimeCountdownInterval = 500;//地磅接收超时,倒计时 ,默认50毫数一次
double recentlyValidWeightNum = 0.0;//最近一次有效读磅数
3、自定义地磅状态
public enum PoundStatus {UN_CONNECTED(-1),//未连接UNSTABLE(0),//已连接,不稳定STABLE(1);//已连接,已稳定int code;
PoundStatus(int code) {this.code = code;
}
public String getStatusStr() {return code == -1 ? "未连接" : (code == 0 ? "不稳定" : "稳定");}
}
三、连接地磅代码解析
1、增加一个串口管理依赖
gradle 下添加依赖 implementation 'com.github.547394:SerialPortManager:1.0.10'
2、新建一个PoundManager.java 增加上面的相关配置参数
public class PoundManager {static PoundManager instance;//唯一实例SerialPortManager serialPort;//端口管理器SerialPortProtocol protocol = new SerialPortProtocol();//端口协议String port = "/dev/ttyS1";//串口名字,默认ttfS1int baudRate = 9600;//波特率,默认9600int stableTimeMills = 1000;//地磅稳定时间,超过这个时间数据不曾修改则表示地磅稳定,耀华的是1秒CountDownTimer countDownTimer;//地磅信号接收超时倒计时int receiveTimeOut = 1000;//地磅接收超时,一般地磅会毫秒内发送数据,超过这个时间则表示地磅链接失败,默认是1秒没内收到数据就表示地磅链接失败int receiveTimeCountdownInterval = 500;//地磅接收超时,倒计时 ,默认50毫数一次,int dateLengthPerFrame = 8;//每一帧的数据长度 ,耀华是8位PoundStatusListener poundStatusListener;//地磅状态监听器PoundStatus poundStatus = PoundStatus.UN_CONNECTED;//地磅状态,默认未连接double recentlyValidWeightNum = 0.0;//最近一次有效读磅数long lastValidWeightNumTimeMills;//最后一次有效读数时间long lastDataReceiveTime;//最后一次监听到数据输入的时间public static PoundManager getInstance() {if (instance == null) {instance = new PoundManager();}return instance;}/*** 地磅信息*/public interface PoundStatusListener {void onTick(double lastValidWeightNum, PoundStatus status);}/*** 地磅状态*/public enum PoundStatus {UN_CONNECTED(-1),//未连接UNSTABLE(0),//已连接,不稳定STABLE(1);//已连接,已稳定int code;PoundStatus(int code) {this.code = code;}public String getStatusStr() {return code == -1 ? "未连接" : (code == 0 ? "不稳定" : "稳定");}}}
3、初始化端口连接
//初始化端口设置public void init() {outPutInfo("正在初始化地磅设置");initSettingFromSP();serialPort = new SerialPortManager();protocol.setFixedLength(dateLengthPerFrame);serialPort.setBufferSize(1024);serialPort.setProtocol(protocol);serialPort.setReceivedTimeout(receiveTimeOut);serialPort.enableDebug(true);//是否开启日志serialPort.setOnDataListener(new OnDataListener() {@Overridepublic void onDataReceived(byte[] bytes) {// dealReceiveDataOld(bytes);dealReceiveData(new String(bytes));}@Overridepublic void onDataSend(byte[] bytes) {super.onDataSend(bytes);}});serialPort.setOnOpenListener(new OnOpenListener() {@Overridepublic void onSuccess(File device) {super.onSuccess(device);
// poundStatus = PoundStatus.UNSTABLE;
// outPutInfo("地磅连接成功,开始监听数据返回");startListeningPortCountDown();}@Overridepublic void onFailure(File device, SerialPortError error) {super.onFailure(device, error);outPutInfo("地磅连接失败:" + error.toString());startListeningPortCountDown();}});outPutInfo("正在链接地磅");serialPort.open(port, baudRate);}
4、处理接受到的数据
StringBuilder tempReceiveStr;//为了防止重复new,定义一个自由成员变量private void dealReceiveData(String bytes) {try {if (bytes.length() <= 1) return;tempReceiveStr = new StringBuilder(bytes).delete(0,1).reverse();Log.v("wztest", "tempStr=" +tempReceiveStr.toString());try {if (tempReceiveStr.length() != 0) {//有数据if (Double.parseDouble(tempReceiveStr.toString()) != recentlyValidWeightNum) {//数据不同,表示数据有变动,不稳定recentlyValidWeightNum = Double.parseDouble(tempReceiveStr.toString());lastValidWeightNumTimeMills = System.currentTimeMillis();poundStatus = PoundStatus.UNSTABLE;} else {//数据不变,判断是否稳定poundStatus = System.currentTimeMillis() - lastValidWeightNumTimeMills > stableTimeMills ? PoundStatus.STABLE : PoundStatus.UNSTABLE;}}} catch (Exception e) {e.printStackTrace();recentlyValidWeightNum = 0.0;poundStatus = PoundStatus.UNSTABLE;// Log.v("wztest", "数据中包含了无效数字");}lastDataReceiveTime = System.currentTimeMillis();//输入日志和回调outPutInfo("收到地磅数据,最近一条有效数据为:" + recentlyValidWeightNum);} catch (Exception e) {outPutInfo("地磅信息解析错误:" + new String(bytes));e.printStackTrace();lastValidWeightNumTimeMills = System.currentTimeMillis();poundStatus = PoundStatus.UNSTABLE;}}
5、监听者模式+倒计时返回设备实时状态
//监听串口数据读入倒计时//50年有效private void startListeningPortCountDown() {countDownTimer = new CountDownTimer(1000 * 60 * 60 * 24 * 365 * 50, 500) {@Overridepublic void onTick(long millisUntilFinished) {if (System.currentTimeMillis() - lastDataReceiveTime > receiveTimeOut) {poundStatus = PoundStatus.UN_CONNECTED;recentlyValidWeightNum = 0.0;outPutInfo("地磅连接超时");}}@Overridepublic void onFinish() {//50年未关机?}}.start();}public void onDestroy() {if (countDownTimer != null) countDownTimer.cancel();if (instance != null) instance = null;}public PoundStatusListener getPoundStatusListener() {return poundStatusListener;}public PoundManager setPoundStatusListener(PoundStatusListener poundStatusListener) {this.poundStatusListener = poundStatusListener;return this;}/*** 输出日志和回调** @param message*/void outPutInfo(String message) {Log.v("PoundManager", message == null ? "" : message);if (poundStatusListener != null) {poundStatusListener.onTick(recentlyValidWeightNum, poundStatus);}}
6、最后调用使用
PoundManager.getInstance().setPoundStatusListener(new PoundManager.PoundStatusListener() {@Overridepublic void onTick(double lastValidWeightNum, PoundManager.PoundStatus status) {runOnUiThread(new Runnable() {@Overridepublic void run() {tv_num.setText(String.valueOf(lastValidWeightNum));tv_hint.setText(status.getStatusStr());tv_num.setTextColor(status == PoundManager.PoundStatus.STABLE ? Color.rgb(0, 255, 0) : Color.rgb(255, 0, 0));tv_hint.setTextColor(status == PoundManager.PoundStatus.STABLE ? Color.rgb(0, 255, 0) : Color.rgb(255, 0, 0));}});}}).init();
这样就正常接入了.
四、过程中遇到的问题和解决方案
1、第一个问题是地磅连接电脑可以互相接收数据,工控机连接电脑可以互相接收数据,但是地磅连接工控机就无法接收数据。
这个问题造成的原因是工控机串口线接错了 ,RS232串口线一般2是输出信号,3是输入信号,工控机那边接错线,把输入和输出接错了。
按道理工控机接错了,则工控机的输出变成了输入,那么连接到电脑,应该是无法互相接收数据的(电脑端的输入没信号了)
但是非常非常巧合的是,我买了一条双目数据线正好也是接错的,结果负负得正,反而把数据转换过来了!!!
最后拆了三个串口线发现了上面的原理,改一下针口解决了。
2、数据一次性接收的不是8位 , 而是多串数据在一次接收中
这个主要是因为没有在协议上设置一次接收数据长度,
protocol.setFixedLength(dateLengthPerFrame);
完整代码:
package com.jda.app.main.utils;import android.content.Context;
import android.os.CountDownTimer;
import android.util.Log;import com.tim.serialportlib.OnDataListener;
import com.tim.serialportlib.OnOpenListener;
import com.tim.serialportlib.SerialPortError;
import com.tim.serialportlib.SerialPortManager;
import com.tim.serialportlib.SerialPortProtocol;import java.io.File;/*** CreateInfo:* wz created on 2021/1/27;* Email 37717239@qq.com.* <p>* Description:* gradle 下添加依赖 implementation 'com.github.547394:SerialPortManager:1.0.10'* 耀华地磅管理工具*/
public class PoundManager {static PoundManager instance;//唯一实例SerialPortManager serialPort;//端口管理器SerialPortProtocol protocol = new SerialPortProtocol();//端口协议String port = "/dev/ttyS1";//串口名字,默认ttfS1int baudRate = 9600;//波特率,默认9600int stableTimeMills = 1000;//地磅稳定时间,超过这个时间数据不曾修改则表示地磅稳定,耀华的是1秒CountDownTimer countDownTimer;//地磅信号接收超时倒计时int receiveTimeOut = 1000;//地磅接收超时,一般地磅会毫秒内发送数据,超过这个时间则表示地磅链接失败,默认是1秒没内收到数据就表示地磅链接失败int receiveTimeCountdownInterval = 500;//地磅接收超时,倒计时 ,默认50毫数一次,int dateLengthPerFrame = 8;//每一帧的数据长度 ,耀华是8位PoundStatusListener poundStatusListener;//地磅状态监听器PoundStatus poundStatus = PoundStatus.UN_CONNECTED;//地磅状态,默认未连接double recentlyValidWeightNum = 0.0;//最近一次有效读磅数long lastValidWeightNumTimeMills;//最后一次有效读数时间long lastDataReceiveTime;//最后一次监听到数据输入的时间public static PoundManager getInstance() {if (instance == null) {instance = new PoundManager();}return instance;}//初始化端口设置public void init() {outPutInfo("正在初始化地磅设置");initSettingFromSP();serialPort = new SerialPortManager();protocol.setFixedLength(dateLengthPerFrame);serialPort.setBufferSize(1024);serialPort.setProtocol(protocol);serialPort.setReceivedTimeout(receiveTimeOut);serialPort.enableDebug(true);//是否开启日志serialPort.setOnDataListener(new OnDataListener() {@Overridepublic void onDataReceived(byte[] bytes) {// dealReceiveDataOld(bytes);dealReceiveData(new String(bytes));}@Overridepublic void onDataSend(byte[] bytes) {super.onDataSend(bytes);}});serialPort.setOnOpenListener(new OnOpenListener() {@Overridepublic void onSuccess(File device) {super.onSuccess(device);
// poundStatus = PoundStatus.UNSTABLE;
// outPutInfo("地磅连接成功,开始监听数据返回");startListeningPortCountDown();}@Overridepublic void onFailure(File device, SerialPortError error) {super.onFailure(device, error);outPutInfo("地磅连接失败:" + error.toString());startListeningPortCountDown();}});outPutInfo("正在链接地磅");serialPort.open(port, baudRate);}StringBuilder tempReceiveStr;//为了防止重复new,定义一个自由成员变量private void dealReceiveData(String bytes) {try {if (bytes.length() <= 1) return;tempReceiveStr = new StringBuilder(bytes).delete(0,1).reverse();Log.v("wztest", "tempStr=" +tempReceiveStr.toString());try {if (tempReceiveStr.length() != 0) {//有数据if (Double.parseDouble(tempReceiveStr.toString()) != recentlyValidWeightNum) {//数据不同,表示数据有变动,不稳定recentlyValidWeightNum = Double.parseDouble(tempReceiveStr.toString());lastValidWeightNumTimeMills = System.currentTimeMillis();poundStatus = PoundStatus.UNSTABLE;} else {//数据不变,判断是否稳定poundStatus = System.currentTimeMillis() - lastValidWeightNumTimeMills > stableTimeMills ? PoundStatus.STABLE : PoundStatus.UNSTABLE;}}} catch (Exception e) {e.printStackTrace();recentlyValidWeightNum = 0.0;poundStatus = PoundStatus.UNSTABLE;// Log.v("wztest", "数据中包含了无效数字");}lastDataReceiveTime = System.currentTimeMillis();//输入日志和回调outPutInfo("收到地磅数据,最近一条有效数据为:" + recentlyValidWeightNum);} catch (Exception e) {outPutInfo("地磅信息解析错误:" + new String(bytes));e.printStackTrace();lastValidWeightNumTimeMills = System.currentTimeMillis();poundStatus = PoundStatus.UNSTABLE;}}/***** 第一版处理数据方式 ,通过=号分割处理,* 临时备份, 准备第二个更加有效率的方式处理* @param bytes*/private void dealReceiveDataOld(byte[] bytes) {try {if (bytes.length == 0) return;String[] splitList = new String(bytes).split("=");//耀华的称重数据解析
// Log.v("wztest", "收到消息" + new String(bytes) + " 分割数组长度" + splitList.length);boolean containsDifferentNum = false;//数据段是否包含与最近称重不同数据for (int i = 0; i < splitList.length; i++) {// Log.v("wztest", "第" + i + "个数据" + splitList[i]);try {if (!splitList[i].equals("")) {if (Double.parseDouble(splitList[i]) != recentlyValidWeightNum) {//发现不同数据,表示数据有变动containsDifferentNum = true;break;
// Log.v("wztest", "数据中发现了不同数字");}}} catch (Exception e) {e.printStackTrace();containsDifferentNum = true;
// Log.v("wztest", "数据中包含了无效数字");}}if (containsDifferentNum) {//如果数据不一致,则刷新最近一条有效信息的时间为当前时间,并且将数据置为不稳定lastValidWeightNumTimeMills = System.currentTimeMillis();poundStatus = PoundStatus.UNSTABLE;try {recentlyValidWeightNum = Double.parseDouble(splitList[splitList.length - 1]);
// Log.v("wztest", "设置有效数据为最后一个数据" + recentlyValidWeightNum);} catch (Exception e) {e.printStackTrace();recentlyValidWeightNum = 0.0;
// Log.v("wztest", "最后一个数据不是有效数字");}} else {//数据与以前一致,则判断最近一次时间与当前时间是否超过了稳定期,超过则表示稳定,未超过则表示不稳定poundStatus = System.currentTimeMillis() - lastValidWeightNumTimeMills > stableTimeMills ? PoundStatus.STABLE : PoundStatus.UNSTABLE;}lastDataReceiveTime = System.currentTimeMillis();//输入日志和回调outPutInfo("收到地磅数据,最近一条有效数据为:" + recentlyValidWeightNum);} catch (Exception e) {outPutInfo("地磅信息解析错误:" + new String(bytes));e.printStackTrace();lastValidWeightNumTimeMills = System.currentTimeMillis();poundStatus = PoundStatus.UNSTABLE;}}//监听串口数据读入倒计时//50年有效private void startListeningPortCountDown() {countDownTimer = new CountDownTimer(1000 * 60 * 60 * 24 * 365 * 50, 500) {@Overridepublic void onTick(long millisUntilFinished) {if (System.currentTimeMillis() - lastDataReceiveTime > receiveTimeOut) {poundStatus = PoundStatus.UN_CONNECTED;recentlyValidWeightNum = 0.0;outPutInfo("地磅连接超时");}}@Overridepublic void onFinish() {//50年未关机?}}.start();}public void onDestroy() {if (countDownTimer != null) countDownTimer.cancel();if (instance != null) instance = null;}public PoundStatusListener getPoundStatusListener() {return poundStatusListener;}public PoundManager setPoundStatusListener(PoundStatusListener poundStatusListener) {this.poundStatusListener = poundStatusListener;return this;}/*** 输出日志和回调** @param message*/void outPutInfo(String message) {Log.v("PoundManager", message == null ? "" : message);if (poundStatusListener != null) {poundStatusListener.onTick(recentlyValidWeightNum, poundStatus);}}//这里执行一些地磅设置缓存读取,比如波特率修改、端口修改private void initSettingFromSP() {}public boolean checkPoundEnvironment(Context context) {return false;}public void setBaudRate(int baudRate) {this.baudRate = baudRate;}public int getBaudRate() {return this.baudRate;}public void setPort(String port) {this.port = port;}public String getPort() {return this.port;}/*** 地磅信息*/public interface PoundStatusListener {void onTick(double lastValidWeightNum, PoundStatus status);}/*** 地磅状态*/public enum PoundStatus {UN_CONNECTED(-1),//未连接UNSTABLE(0),//已连接,不稳定STABLE(1);//已连接,已稳定int code;PoundStatus(int code) {this.code = code;}public String getStatusStr() {return code == -1 ? "未连接" : (code == 0 ? "不稳定" : "稳定");}}
}
《硬件接入》耀华XK3190-A9+地磅安卓(java)接入过程分享相关推荐
- 耀华仪表A9数据解析(C#)
耀华仪表A9 数据解析,磨蹭一中午,终于把他解析出来了,测试了一下午感觉很完美,在这里分享给大家:废话不说,直接贴代码:顺便给大家推荐一个开源称重软件,git 码云地址:https://gitee.c ...
- 上海耀华地磅串口开发(C#)
上海耀华地磅串口开发(C#) 耀华地磅通用的型号为XK3190-DS3q1和电脑采用DB9接线方式,RS232协议传输. 如果需要转接 接线正常后我们开始通过C#遍历计算机所有的串口设备 打开串口 接 ...
- 用计算机设置仪表通讯地址,教你耀华XK3190-A9+仪表接电脑通讯协议
原标题:教你耀华XK3190-A9+仪表接电脑通讯协议 ▲!通讯接口输出引线与计算机联接必须准确无误,倘若联接错误,将损坏仪表输出端口或计算机通讯输入端口,甚至严重损坏仪表和计算机及相应的外部设备. ...
- 荔枝FM架构师刘耀华:异地多活IDC机房架构
声明:本文首发于CSDN,禁止未经许可的任何形式转载,可咨询文末的责编. 多机房架构存在的原因 单机房一旦死机,断电.维护根本无法挽回整个数据,想离线读取等都不行.当一个机房不可用,所有的业务就都不可 ...
- EasyCVR平台接入大华EVS存储服务器,需要注意哪些事项?
EasyCVR支持多类型设备.多协议方式接入,平台支持设备通过国标GB28181.RTMP.RTSP/Onvif.海康SDK.大华SDK.Ehome等协议接入,对外可分发RTSP.RTMP.FLV.H ...
- php大华视频监控接入,大华摄像头实时视频接入Demo
[实例简介] 亲测可用,这是使用大华sdk接入大华摄像头实时视频的winform测试程序 [实例截图] [核心代码] 大华摄像头实时视频demo-源码 ├── NetSDKCS │ ├── bin ...
- EasyCVR接入大华CVS录像机,下载录像文件名为空是如何解决的?
EasyCVR视频融合云服务是TSINGSEE青犀视频研发的一款支持接入协议最全面的视频监控平台,除了标准协议(国标GB/T28181.Onvif.RTSP协议等),还支持厂家的私有协议(海康SDK. ...
- 侯耀文两女告侯耀华争遗产
郭德纲博客截图 本报讯 (记者王丽娜)著名相声表演艺术家侯耀文去世已两年.因其生前未立遗嘱,他的身后遗产尚未分配.记者昨天获悉,认为伯父侯耀华等三人侵占自己父亲的遗产,侯耀文女儿侯瓒及其妹妹将对方 ...
- c语言编程求macd最大值,2010年天津工业大学耀华杯计算机竞赛试卷(C语言全卷带答案).doc...
您所在位置:网站首页 > 海量文档  > 高等教育 > 习题/试题 2010年天津工业大学耀华杯计算机竞赛试卷(C语言 ...
最新文章
- 阿里前员工跳槽后曝光薪资截图:新公司月入五万多,很满足!
- LINUX内核分析第四周——扒开系统调用的三层皮
- [JVM]常用JVM工具使用
- CentOS7.9关闭SELinux
- C++重载(overload)和重写(覆盖)的区别?
- Xamarin Android 所见即所得问题
- eclipse开发cocos2dx 3.2环境搭建之二: cocos2dx 3.2安装及测试运行 (An internal error occurred during: “C/C++ Indexe)
- 线性表----链式表
- AM335 嵌入式 linux,am335x开发板建立嵌入式 Linux NFS 开发环境
- ImportError: No module named ‘pandas.io.data‘
- (97)Verilog HDL:秒灯设计
- Victor and World(spfa+状态压缩dp)
- 《乔布斯的魔力演讲》书摘
- 阿里云域名绑定IP手把手教学
- 加域电脑如何取消锁屏
- 工信部:将于近期发放5G商用牌照
- LeetCode精选101刷题必备(C++)-附详细分类及解体说明
- Python模拟Tim登录界面
- 基于STM32的外围系统设计
- First part of my Spring posts is refreshed