From 1752a4cd5b1bccd2fa3c178e8dca566406cb848b Mon Sep 17 00:00:00 2001 From: zhaohe Date: Fri, 26 Jul 2024 15:12:10 +0800 Subject: [PATCH] update --- src/main/java/a8k/appbean/OptScanDirection.java | 9 +++ src/main/java/a8k/canbus/A8kCanBusService.java | 49 ++++++++++++- src/main/java/a8k/canbus/protocol/CmdId.java | 13 +--- src/main/java/a8k/opt_algo/A8kOptAlgo.java | 77 +++++++++++++++++++++ .../ReactionPlatesTransmitCtrlService.java | 53 ++++++++++++++ zhaohe_app.db | Bin 487424 -> 487424 bytes 6 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 src/main/java/a8k/appbean/OptScanDirection.java create mode 100644 src/main/java/a8k/opt_algo/A8kOptAlgo.java diff --git a/src/main/java/a8k/appbean/OptScanDirection.java b/src/main/java/a8k/appbean/OptScanDirection.java new file mode 100644 index 0000000..12b5614 --- /dev/null +++ b/src/main/java/a8k/appbean/OptScanDirection.java @@ -0,0 +1,9 @@ +package a8k.appbean; + +public enum OptScanDirection { + POSITIVE, NEGATIVE; + + public Integer getInteger() { + return this == POSITIVE ? 1 : -1; + } +} diff --git a/src/main/java/a8k/canbus/A8kCanBusService.java b/src/main/java/a8k/canbus/A8kCanBusService.java index a7c6543..5cc2733 100644 --- a/src/main/java/a8k/canbus/A8kCanBusService.java +++ b/src/main/java/a8k/canbus/A8kCanBusService.java @@ -1,6 +1,7 @@ package a8k.canbus; import a8k.app_eventbus.appevent.A8kCanBusOnConnectEvent; +import a8k.appbean.OptScanDirection; import a8k.appbean.PlateInfo; import a8k.canbus.custom_param_mgr.A8kModCustomParamMgr; import a8k.canbus.protocol.*; @@ -154,7 +155,53 @@ public class A8kCanBusService { } - //plate_code_scaner_adc_readraw + // ka8k_opt_v2_t_start_scan = CMDID(7, 0), //(int32_t scanDirection, int32_t lasterGain,int32_t scanGain) + // ka8k_opt_v2_f_start_scan = CMDID(7, 1), //(int32_t scanDirection, int32_t lasterGain,int32_t scanGain) + // ka8k_opt_v2_f_readVal = CMDID(7, 15), //(int32_t *val0,int32_t *val1) for_debug + + // a8k_opt_v2_t_start_scan(0x0700, "a8k_opt_v2_t_start_scan"),// + // a8k_opt_v2_f_start_scan(0x0701, "a8k_opt_v2_f_start_scan"),// + // a8k_opt_v2_t_open_laster(0x070a, "a8k_opt_v2_t_open_laster"),// + // a8k_opt_v2_t_close_laster(0x070b, "a8k_opt_v2_t_close_laster"),// + // a8k_opt_v2_t_readVal(0x070c, "a8k_opt_v2_t_readVal"),// + // a8k_opt_v2_f_open_laster(0x070d, "a8k_opt_v2_f_open_laster"),// + // a8k_opt_v2_f_close_laster(0x070e, "a8k_opt_v2_f_close_laster"),// + // a8k_opt_v2_f_readVal(0x070f, "a8k_opt_v2_f_readVal"),// + + //a8k_opt_v2_read_raw + + + public void optTStartScan(MId id, OptScanDirection scanDirection, Integer lasterGain, Integer scanGain) throws HardwareException, InterruptedException { + callcmd(id.toInt(), CmdId.a8k_opt_v2_t_start_scan.toInt(), scanDirection.getInteger(), lasterGain, scanGain); + } + + public void optTStartScanBlock(MId id, OptScanDirection scanDirection, Integer lasterGain, Integer scanGain, Integer actionOvertime) throws HardwareException, InterruptedException { + optTStartScan(id, scanDirection, lasterGain, scanGain); + waitForMod(id, actionOvertime); + } + + public void optFStartScan(MId id, OptScanDirection scanDirection, Integer lasterGain, Integer scanGain) throws HardwareException, InterruptedException { + callcmd(id.toInt(), CmdId.a8k_opt_v2_f_start_scan.toInt(), scanDirection.getInteger(), lasterGain, scanGain); + } + + public void optFStartScanBlock(MId id, OptScanDirection scanDirection, Integer lasterGain, Integer scanGain, Integer actionOvertime) throws HardwareException, InterruptedException { + optFStartScan(id, scanDirection, lasterGain, scanGain); + waitForMod(id, actionOvertime); + } + + public List optReadRaw(MId id) throws HardwareException, InterruptedException { + int i = 0; + List result = new ArrayList<>(); + while (true) { + var rxPacket = callcmd(id.toInt(), CmdId.a8k_opt_v2_read_raw.toInt(), i++); + if (rxPacket.getCmdContent().length == 0) { + break; + } + var rawdata = ByteArray.readU16bitArray(rxPacket.getCmdContent()); + result.addAll(Arrays.asList(rawdata)); + } + return result; + } public void plateCodeScanerPushCardAndScan(MId id, Integer finalStopPos) throws HardwareException, InterruptedException { diff --git a/src/main/java/a8k/canbus/protocol/CmdId.java b/src/main/java/a8k/canbus/protocol/CmdId.java index 258b209..43f9c62 100644 --- a/src/main/java/a8k/canbus/protocol/CmdId.java +++ b/src/main/java/a8k/canbus/protocol/CmdId.java @@ -47,17 +47,8 @@ public enum CmdId { pipette_aspirate_llf(0x720c, "pipette_aspirate_llf"),// pipette_distribut_llf(0x720d, "pipette_distribut_llf"),// pipette_shake_up_llf(0x720e, "pipette_shake_up_llf"),// - // - a8000_optical_module_power_ctrl(0x0600, "a8000_optical_module_power_ctrl"),// - a8000_optical_open_laser(0x0601, "a8000_optical_open_laser"),// - a8000_optical_close_laser(0x0602, "a8000_optical_close_laser"),// - a8000_optical_set_laster_gain(0x0603, "a8000_optical_set_laster_gain"),// - a8000_optical_set_scan_amp_gain(0x0604, "a8000_optical_set_scan_amp_gain"),// - a8000_optical_read_scanner_adc_val(0x0605, "a8000_optical_read_scanner_adc_val"),// - a8000_optical_read_laster_adc_val(0x0606, "a8000_optical_read_laster_adc_val"),// - a8000_optical_scan_current_point_amp_adc_val(0x0607, "a8000_optical_scan_current_point_amp_adc_val"),// - a8000_optical_start_capture(0x0608, "a8000_optical_start_capture"),// - a8000_optical_read_raw(0x0609, "a8000_optical_read_raw", CmdId.ATTACH_IS_INT32, CmdId.ATTACH_IS_BYTES),// + + a8k_opt_v2_read_raw(0x0609, "a8k_opt_v2_read_raw", CmdId.ATTACH_IS_INT32, CmdId.ATTACH_IS_BYTES),// // a8k_opt_v2_t_start_scan(0x0700, "a8k_opt_v2_t_start_scan"),// a8k_opt_v2_f_start_scan(0x0701, "a8k_opt_v2_f_start_scan"),// diff --git a/src/main/java/a8k/opt_algo/A8kOptAlgo.java b/src/main/java/a8k/opt_algo/A8kOptAlgo.java new file mode 100644 index 0000000..40d803e --- /dev/null +++ b/src/main/java/a8k/opt_algo/A8kOptAlgo.java @@ -0,0 +1,77 @@ +package a8k.opt_algo; + +import java.util.ArrayList; +import java.util.List; + +public class A8kOptAlgo { + + static private List createDoubleList(int size) { + List list = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + list.add(0.0); + } + return list; + } + + static private List integerToDouble(List input) { + List output = new ArrayList<>(input.size()); + for (Integer i : input) { + output.add(i.doubleValue()); + } + return output; + } + + static private List doubleToInteger(List input) { + List output = new ArrayList<>(input.size()); + for (Double i : input) { + output.add(i.intValue()); + } + return output; + } + + static public List preProcessOptData(List input) { + List inputRaw = integerToDouble(input); + List upSamplingRaw = superSampling(inputRaw, 24); + List subSamplingRaw = subSampling(upSamplingRaw, 5); + return doubleToInteger(subSamplingRaw); + } + + + static public List superSampling(List input, Integer factor) { + int outputLength = input.size() * factor; + List upSamplingRaw = createDoubleList(outputLength); + + for (int si = 0, di = 0; si < input.size() - 1; di++) { + Double a = upSamplingRaw.set(di * factor, input.get(si)); + Double b = upSamplingRaw.set((di + 1) * factor, input.get(++si)); + + Double slope = (b - a) / factor; + + for (int i = 0; i < factor - 1; i++) { + int baseIndex = (di * factor) + i; + upSamplingRaw.set(baseIndex + 1, upSamplingRaw.get(baseIndex) + slope); + } + } + return upSamplingRaw; + } + + static public List subSampling(List inputRaw, Integer nSubSampleRate) { + int nSum = 0; + double fAvg = 0.0; + int subIndex = 0; + int nOutputLength = inputRaw.size() / nSubSampleRate; + + List subSampledRaw = createDoubleList(nOutputLength); + + for (int index = 0; index < inputRaw.size(); index++) { + if (index % nSubSampleRate == 0 && index > 0) { + fAvg = (double) nSum / nSubSampleRate; + subSampledRaw.set(subIndex++, fAvg); + nSum = 0; + } + nSum += inputRaw.get(index); + } + subSampledRaw.set(nOutputLength - 1, subSampledRaw.get(nOutputLength - 2)); + return subSampledRaw; + } +} diff --git a/src/main/java/a8k/service/hardware/ReactionPlatesTransmitCtrlService.java b/src/main/java/a8k/service/hardware/ReactionPlatesTransmitCtrlService.java index 96fb549..cc081d8 100644 --- a/src/main/java/a8k/service/hardware/ReactionPlatesTransmitCtrlService.java +++ b/src/main/java/a8k/service/hardware/ReactionPlatesTransmitCtrlService.java @@ -6,6 +6,7 @@ import a8k.canbus.protocol.IOId; import a8k.canbus.protocol.MId; import a8k.appbean.ecode.AppRet; import a8k.canbus.A8kCanBusService; +import a8k.opt_algo.A8kOptAlgo; import a8k.utils.*; import jakarta.annotation.Resource; import org.slf4j.Logger; @@ -31,6 +32,11 @@ public class ReactionPlatesTransmitCtrlService implements HardwareCtrlModule { return hpReader.getInteger("actionOvertime", 7000); } + @HardwareServiceParam(name = "光学扫描超时时间", group = "基础参数") + public Integer getOptScanOvertime() { + return hpReader.getInteger("optScanOvertime", 10000); + } + @HardwareServiceParam(name = "板夹仓通道0位置", group = "板夹仓参数") public Integer getPBCh0Pos() { return hpReader.getInteger("PBCh0Pos", -17); @@ -92,6 +98,27 @@ public class ReactionPlatesTransmitCtrlService implements HardwareCtrlModule { return hpReader.getInteger("OptScanScandbyPos", 305); } + @HardwareServiceParam(name = "T光学扫描起始坐标", group = "光学模组参数") + public Integer getTOptPosOffset() { + return hpReader.getInteger("TOptPosOffset", 3723); + } + + @HardwareServiceParam(name = "F光学扫描起始坐标", group = "光学模组参数") + public Integer getFOptPosOffset() { + return hpReader.getInteger("FOptPosOffset", 2559); + } + + @HardwareServiceParam(name = "T光学发光增益", group = "光学模组参数") + public Integer getOptTLasterGain() { + return hpReader.getInteger("OptTLasterGain", 0); + } + + @HardwareServiceParam(name = "F光学发光增益", group = "光学模组参数") + public Integer getOptFLasterGain() { + return hpReader.getInteger("OptFLasterGain", 0); + } + + /** * ZERO_DPOS */ @@ -325,6 +352,32 @@ public class ReactionPlatesTransmitCtrlService implements HardwareCtrlModule { return AppRet.success(new A8kScanCurve(scanDataCurve, refLine)); } + private AppRet packetOptDisplayScanCurve(List scanDataCurve) { + A8kScanCurve scanCurve = new A8kScanCurve(); + scanCurve.scanDataCurve = A8kOptAlgo.preProcessOptData(scanDataCurve); + scanCurve.refCurve = A8kOptAlgo.preProcessOptData(scanDataCurve); + scanCurve.refLine = new ArrayList<>(); + for (int i = 1; i < 6; i++) { + scanCurve.refLine.add(40 * i); + } + return AppRet.success(scanCurve); + } + + @HardwareServiceAction(name = "T光学扫码", group = "光学调试") + public AppRet optTScan(OptScanDirection direction, Integer scanerGain) throws HardwareException, InterruptedException { + canBus.optTStartScanBlock(MId.OptMod, direction, getOptTLasterGain(), scanerGain, getOptScanOvertime()); + return packetOptDisplayScanCurve(canBus.optReadRaw(MId.OptMod)); + } + + @HardwareServiceAction(name = "F光学扫码", group = "光学调试") + public AppRet optFScan(OptScanDirection direction, Integer scanerGain) throws HardwareException, InterruptedException { + canBus.optFStartScanBlock(MId.OptMod, direction, getOptTLasterGain(), scanerGain, getOptScanOvertime()); + return packetOptDisplayScanCurve(canBus.optReadRaw(MId.OptMod)); + } + + // + // 状态 + // @HardwareServiceAction(name = "读取<转盘>位置", group = "位置测量") public AppRet readTrunablePos() throws HardwareException, InterruptedException { diff --git a/zhaohe_app.db b/zhaohe_app.db index 11ba095d39535eb9bf339c131e752282da8242fe..e7d9ec37461d760d248d30f212b012c0f5ead012 100644 GIT binary patch delta 4393 zcmcInZ)_Ar6yMuxw=KQvH6aa&p)G|LXvyfz?(EF221LO4ms}}5uoCfRXJ?_YwB>rO ze}FEM7!yB1qHH97&`3y(20x$>zo8_?1RFnUVwCC!6B81RiTK3?-`+u`6ncxuZT9jq z`|{qr_vZcHZw}A4AD(SLdY^vehhxh(!T+np*NUl6i~7m2u(fGM%SE~STQ0T)Evf7~ z+4Y(4GEoko2{F! z>qvi@9!|IDAL&n~eo9TJy0p)=q6WX``;5W^d2K1NO{M&RA<9h$QOrE#Do-Fc2ts1o z#G}~b`SJ30DMsVh_g?NFn;1|+mWRhi`$t4sO$?UA=)}I^^5$}BWVf2v@Gp3H6wx1}96SW#NseI1ccDYvzZz9OFH!jlx5*3nfjDN`kns6r!#r zk;iNjBH>fdr-6$lv*&!oQ9M1oe{$GQ<_R;5i#?TUx7n^~Gb#couOg5t7gD7-L!Puf z)AX?IaXIHG?4O+2o6HBZak1MdkoZ7RimB~W#2m|nat9bWuHz#|(!f&!j#^;HhE=I@ zq{^c7Z^h@=B%F7mT!x2M8HH8gLb{Szt^tq<_=qz1zoy z93I_Mvlu3`cde|RC5PF*W5$QoGD9f0&j@m{OCU|u5nkXzL&)m(A03SgP}4Xe4DaYN z3hl6QhjL4DNV>x-t-v5Hj_V`aWG-}+4SnLr8^;yHVT~SxBe;7-CFwa6>W7uXk!eG5 zsm(d$Mqs3vusI2Y%eVtgymicvlRm0STepnY+Gt4xNgV6bWIrD}eXxBw5kIw~-cqnw%n2jiZJ0Vbpugvh}hqOq_q9gEtO z(rOHGmnF5{UbSvIO1VM`1hs`z2~mI_lOrB@)N!QiGFiol3E2No)p%G7UHYsAoa4NLLaDSajl zf0l9fu%7CFu4RMP+I(8e3}ibq2eKzJz0Ieymoqb&D=lr=$D6;+oXlRxXxaVo1H<7C zpEF&p=NrSd=|T!)6)+cy!CZg{iWM}Rg*l*iAerYAW>Rlm%LaYVA~R%eg!F;ph9sk) z7ZlsVB$&RoWkc$65_nz%iWhDJvhy%@H7K5lF*2+Ll0BfgKMB-zgW}^!0BaQ}c3y{{ zFvg$T!Ou#l|CJY(N4PJgc-)$24Z^+oj1LA|@a8N|1v7k<=x;>Gdk&1=$QQT`BoZiK~-=$GoE_Ggs4 zR8iEvjX=;w#5PSWCm&wrDUGbr9D^AA@*mR>zImjHR_2nih48>s?_H zSk#?9$ynE1$1Fy=!rQX0j8*^eU9qnDGkD$zj!9R>s=L&a5APA{0_#VTkgo79SQq%{ zT!eMa1B5v)bQ9^SIT}dJx-wS!EJSl>tSb@e3S*8xS?7OZO_l;47Mg^OPPAOP(`Y&{A7&#}g9tg9yJ0^@;q?^xFjq{}j3tfXfmeo)^L zOB2ztgZi_v)E51AP=5v_{j=z)L;650$>=?hVCLxARgY>*<7v|!bx!Mj@G*5R+B#kN zm=eA5N0>U@(Zy*U#UC4^zo+$nkhD*t{!rf;OGD9zp+01!a_?%nch7XKIG!u+US||~ z;kuZFmpxLsp691jsXV+-)xM-)_?^P(-;Zx>FzOb%R5oR<57!l;;GRuQ4tID{#B7?! vL%j?eb znx~h?cshpwv*KoDfrG5u#F&lQSR%ODLZ_R{Fo&_kZ~<8pWtgK_qBw!9_cF{8EFl~~ zmbWZ(5K9OEiDUw@0_2&)S;85Ctkv?&k=t1snEv|PGB7YmbFX9IkL6#_H-RUJ zSDvSuZzu08{u_LDJeu6=c;E1x<@v@Z%FoSj!k5nXh`){3gZnzq65hi+47`P#6$J{o zx39a+G=YglgE^FOy0r|m3M)65nSGB*6(TqV&hnQ9N^^jvpTPxzo`EV1lmkk$f~A3; zfCx^L2Z}L+#X>+#CUxde>uc%w-Rl47M`{u>Y5z{Qo`cb`}HXKkv5-1h9XQ2ay5- jZ2>H80j%2s*o+_W8Uwv)1jOY)T(()!-~j(J2X+GhM;vy~