最近遇到在安卓上通过串口连接地磅的需求, 基本上实现了读数和判断地磅稳定状态 , 这里分享出来实现过程以方便大家开发.我们开发用的打印机是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)接入过程分享相关推荐

  1. 耀华仪表A9数据解析(C#)

    耀华仪表A9 数据解析,磨蹭一中午,终于把他解析出来了,测试了一下午感觉很完美,在这里分享给大家:废话不说,直接贴代码:顺便给大家推荐一个开源称重软件,git 码云地址:https://gitee.c ...

  2. 上海耀华地磅串口开发(C#)

    上海耀华地磅串口开发(C#) 耀华地磅通用的型号为XK3190-DS3q1和电脑采用DB9接线方式,RS232协议传输. 如果需要转接 接线正常后我们开始通过C#遍历计算机所有的串口设备 打开串口 接 ...

  3. 用计算机设置仪表通讯地址,教你耀华XK3190-A9+仪表接电脑通讯协议

    原标题:教你耀华XK3190-A9+仪表接电脑通讯协议 ▲!通讯接口输出引线与计算机联接必须准确无误,倘若联接错误,将损坏仪表输出端口或计算机通讯输入端口,甚至严重损坏仪表和计算机及相应的外部设备. ...

  4. 荔枝FM架构师刘耀华:异地多活IDC机房架构

    声明:本文首发于CSDN,禁止未经许可的任何形式转载,可咨询文末的责编. 多机房架构存在的原因 单机房一旦死机,断电.维护根本无法挽回整个数据,想离线读取等都不行.当一个机房不可用,所有的业务就都不可 ...

  5. EasyCVR平台接入大华EVS存储服务器,需要注意哪些事项?

    EasyCVR支持多类型设备.多协议方式接入,平台支持设备通过国标GB28181.RTMP.RTSP/Onvif.海康SDK.大华SDK.Ehome等协议接入,对外可分发RTSP.RTMP.FLV.H ...

  6. php大华视频监控接入,大华摄像头实时视频接入Demo

    [实例简介] 亲测可用,这是使用大华sdk接入大华摄像头实时视频的winform测试程序 [实例截图] [核心代码] 大华摄像头实时视频demo-源码 ├── NetSDKCS │   ├── bin ...

  7. EasyCVR接入大华CVS录像机,下载录像文件名为空是如何解决的?

    EasyCVR视频融合云服务是TSINGSEE青犀视频研发的一款支持接入协议最全面的视频监控平台,除了标准协议(国标GB/T28181.Onvif.RTSP协议等),还支持厂家的私有协议(海康SDK. ...

  8. 侯耀文两女告侯耀华争遗产

      郭德纲博客截图 本报讯 (记者王丽娜)著名相声表演艺术家侯耀文去世已两年.因其生前未立遗嘱,他的身后遗产尚未分配.记者昨天获悉,认为伯父侯耀华等三人侵占自己父亲的遗产,侯耀文女儿侯瓒及其妹妹将对方 ...

  9. c语言编程求macd最大值,2010年天津工业大学耀华杯计算机竞赛试卷(C语言全卷带答案).doc...

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp高等教育&nbsp>&nbsp习题/试题 2010年天津工业大学耀华杯计算机竞赛试卷(C语言 ...

最新文章

  1. 阿里前员工跳槽后曝光薪资截图:新公司月入五万多,很满足!
  2. LINUX内核分析第四周——扒开系统调用的三层皮
  3. [JVM]常用JVM工具使用
  4. CentOS7.9关闭SELinux
  5. C++重载(overload)和重写(覆盖)的区别?
  6. Xamarin Android 所见即所得问题
  7. eclipse开发cocos2dx 3.2环境搭建之二: cocos2dx 3.2安装及测试运行 (An internal error occurred during: “C/C++ Indexe)
  8. 线性表----链式表
  9. AM335 嵌入式 linux,am335x开发板建立嵌入式 Linux NFS 开发环境
  10. ImportError: No module named ‘pandas.io.data‘
  11. (97)Verilog HDL:秒灯设计
  12. Victor and World(spfa+状态压缩dp)
  13. 《乔布斯的魔力演讲》书摘
  14. 阿里云域名绑定IP手把手教学
  15. 加域电脑如何取消锁屏
  16. 工信部:将于近期发放5G商用牌照
  17. LeetCode精选101刷题必备(C++)-附详细分类及解体说明
  18. Python模拟Tim登录界面
  19. 基于STM32的外围系统设计
  20. First part of my Spring posts is refreshed

热门文章

  1. 郑州大学c语言考试系统,郑州大学c语言考试机真题.doc
  2. Nginx做流媒体服务Windows版实现直播
  3. Tailwind CSS 浅析
  4. 练习-在上次关闭位置启动窗口
  5. excel常用函数大全(一)
  6. pythonp爬虫做界面_tkinter 实现爬虫的UI界面
  7. 南京大学地图学与地理信息系统815考研资料
  8. 定位(如何运用定位)
  9. 用fopen写入一个文件
  10. 2160php,[小科普]关于2k、4k、1080p、1440p、2160p等等令人迷惑的叫法