Browse Source

v1.2

master
zhaohe 1 year ago
parent
commit
f6194c6888
  1. 7
      README.md
  2. 2
      iflytoplinuxsdk
  3. 5
      src/configs/gconfig.hpp
  4. 136
      src/service/device_io_control_service.cpp
  5. 14
      src/service/device_io_control_service.hpp
  6. 34
      src/service/disinfection_ctl_service.cpp
  7. 4
      src/service/disinfection_ctl_service.hpp
  8. 55
      src/utils/dvalue_computer.cpp
  9. 16
      src/utils/dvalue_computer.hpp
  10. 43
      src/utils/moving_average_filter.hpp
  11. 81
      src/utils/volume_convertor.cpp
  12. 69
      src/utils/volume_convertor.hpp
  13. 2
      src/version.hpp

7
README.md

@ -3,9 +3,14 @@
```
1.1
v1.1
1.添加打印机逻辑
v1.2
1. D值支持可配置
2. 校准并优化桶内消毒液的体积
3. 平滑消毒液体积显示
```

2
iflytoplinuxsdk

@ -1 +1 @@
Subproject commit 0727f2cfe0574e10d646d841faa3769e9820f1a0
Subproject commit b517025b96b5d3b8608ac462aa41ad6eb10eada5

5
src/configs/gconfig.hpp

@ -20,7 +20,10 @@
marco(int32_t /* */, iflytopSubDeviceCanBitrate, 500000) /*子设备Can设备波特率*/ \
marco(string /* */, pipettingRobotCanIFName, "can1") /*移液臂Can设备名称*/ \
marco(int32_t /* */, pipettingRobotCanBitrate, 500000) /*移液臂Can设备波特率*/ \
marco(int32_t /* */, disinfectantBucketCapacity_g, 2500) /*消毒桶容积*/
marco(int32_t /* */, disinfectantBucketCapacity_g, 2200) /*消毒桶容积*/ \
marco(float /* */, dvalueCoefficient, 1) /*数值越小,相对消毒时间越长*/ \
marco(float /* */, disinfectantWeightPa, 1) /*数值越小,相对消毒时间越长*/ \
marco(float /* */, disinfectantWeightCorrectionFactor, 0.9) /*数值越小,相对消毒时间越长*/
configTemplateDEFILE_CONFIG_SERVICE2( //
GConfig, //

136
src/service/device_io_control_service.cpp

@ -1,4 +1,5 @@
#include "device_io_control_service.hpp"
#include "iflytop/components/uart_printer/uart_printer.hpp"
#include "iflytoplinuxsdk/src/iflytop/components/ziconv.hpp"
using namespace iflytop;
@ -14,18 +15,68 @@ using namespace std;
- 3 PC7 5
#endif
#define GPM_TO_SPEED(gpm) (gpm * 10)
#define SPEED_TO_GPM(speed) (speed / 10)
#define GPM_TO_SPEED(gpm) (gpm * 14.7)
#define SPEED_TO_GPM(speed) (speed / 14.7 + 0.5)
DeviceIoControlService::DeviceIoControlService() {}
void DeviceIoControlService::initialize() { GET_TO_SERVICE(m_zcanHost); }
void DeviceIoControlService::initialize() {
GET_TO_SERVICE(m_zcanHost);
GET_TO_SERVICE(m_config);
}
void DeviceIoControlService::updateDisinfectantVolumeSample(float _pa) {
float pa = _pa - 100; // 100当容器中没有液体时的压强
if (pa < 0) pa = 0;
float g = m_volumeConvertor.pressurePa2VolumeG(_pa) * m_config->get_disinfectantWeightCorrectionFactor();
m_disinfectantVolumeSample_g = m_DisinfectantWeightFilter.filter(g);
// logger->info("pa:{} _pa:{}", _pa, _pa,g);
logger->info("g:{} pa:{} _pa:{}", g, pa, _pa);
}
void DeviceIoControlService::startScan() {
m_workThread.reset(new Thread("DeviceIoControlService", [this]() {
m_PressureSensorDataSampleThread.reset(new Thread("PressureSensorDataSampleThread", [this]() {
ThisThread thisThread;
uint32_t i = 0;
int readpressuresensor_id = 1;
while (!thisThread.getExitFlag()) {
/* code */
ZCanHost::huacheng_pressure_sensor_read_c1005_t sdata;
if (m_zcanHost->huacheng_pressure_sensor_read_c1005(1, sdata) == 0) {
lock_guard<recursive_mutex> lock(lock_);
m_pressure_sensor_data[1] = sdata;
}
thisThread.sleepForMs(100);
if (m_zcanHost->huacheng_pressure_sensor_read_c1005(2, sdata) == 0) {
lock_guard<recursive_mutex> lock(lock_);
m_pressure_sensor_data[2] = sdata;
}
thisThread.sleepForMs(100);
if (m_zcanHost->huacheng_pressure_sensor_read_c1005(3, sdata) == 0) {
lock_guard<recursive_mutex> lock(lock_);
m_pressure_sensor_data[3] = sdata;
}
thisThread.sleepForMs(100);
if (m_zcanHost->huacheng_pressure_sensor_read_c1005(4, sdata) == 0) {
lock_guard<recursive_mutex> lock(lock_);
m_pressure_sensor_data[4] = sdata;
}
thisThread.sleepForMs(100);
{ updateDisinfectantVolumeSample(m_pressure_sensor_data[1].value / 1.0 /*pa*/); }
}
}));
m_workThread.reset(new Thread("DeviceIoControlService", [this]() {
ThisThread thisThread;
uint32_t i = 0;
int error = 0;
int readpressuresensor_id = 1;
while (!thisThread.getExitFlag()) {
/* code */
@ -47,56 +98,22 @@ void DeviceIoControlService::startScan() {
lock_guard<recursive_mutex> lock(lock_);
m_adc_2 = adcv;
}
// m_zcanHost->readadc(1, m_adc_1);
// m_zcanHost->readadc(2, m_adc_2);
// m_zcanHost->readadc(3, m_adc_3);
// m_zcanHost->readadc(4, m_adc_4);
// m_zcanHost->readadc(5, m_adc_5);
}
if (i % 3000 == 0) {
if (i % 3000 == 0 && error < 10) {
// m_hpp272_data_1
ZCanHost::hpp272_data_t m_hpp272_data_1_cache;
int suc = m_zcanHost->hpp272_read_c1000(1, m_hpp272_data_1_cache);
if (suc == 0) {
lock_guard<recursive_mutex> lock(lock_);
m_hpp272_data_1 = m_hpp272_data_1_cache;
error = 0;
} else {
error++;
if (error == 10) {
logger->error("hpp272_read_c1000 error:{}", suc);
}
}
// hydrogen_peroxide_volume
// water_vapor_saturation_pressure_h2o_h2o2
// logger->info("---------hpp272_read_c1000---------");
// logger->info("hydrogen_peroxide_volume :{}", m_hpp272_data_1.hydrogen_peroxide_volume);
// logger->info("h2o_h2o2_rs :{}", m_hpp272_data_1.h2o_h2o2_rs);
// logger->info("temperature1 :{}", m_hpp272_data_1.temperature1);
// logger->info("relative_humidity :{}", m_hpp272_data_1.relative_humidity);
// logger->info("absolute_hydrogen_peroxide :{}", m_hpp272_data_1.absolute_hydrogen_peroxide);
// logger->info("h2o_h2o2dew_point_temperature :{}", m_hpp272_data_1.h2o_h2o2dew_point_temperature);
// logger->info("reserved1 :{}", m_hpp272_data_1.reserved1);
// logger->info("water_volume :{}", m_hpp272_data_1.water_volume);
// logger->info("water_vapor_pressure :{}", m_hpp272_data_1.water_vapor_pressure);
// logger->info("absolute_humidity :{}", m_hpp272_data_1.absolute_humidity);
// logger->info("water_vapor_saturation_pressure_h2o:{}", m_hpp272_data_1.water_vapor_saturation_pressure_h2o);
// logger->info("temperature2 :{}", m_hpp272_data_1.temperature2);
// logger->info("h2o2_vapor_pressure :{}", m_hpp272_data_1.h2o2_vapor_pressure);
// logger->info("water_vapor_saturation_pressure_h2o_h2o2:{}", m_hpp272_data_1.water_vapor_saturation_pressure_h2o_h2o2);
// logger->info("");
}
if (i % 300 == 0) {
if (readpressuresensor_id == 5) {
readpressuresensor_id = 1;
}
ZCanHost::huacheng_pressure_sensor_read_c1005_t sdata;
if (m_zcanHost->huacheng_pressure_sensor_read_c1005(readpressuresensor_id, sdata) == 0) {
lock_guard<recursive_mutex> lock(lock_);
m_pressure_sensor_data[readpressuresensor_id] = sdata;
}
readpressuresensor_id++;
}
if (i % 100 == 0) {
// m_zcanHost->readio(1, m_waterImmersionSensor1);
// m_zcanHost->readio(2, m_waterImmersionSensor2);
}
}
}));
@ -325,19 +342,21 @@ static int filter(int data) {
}
int DeviceIoControlService::getDisinfectantVolume_g() {
// kpa;
lock_guard<recursive_mutex> lock(lock_);
return m_disinfectantVolumeSample_g;
float kpa = m_pressure_sensor_data[1].value / 1000.0;
int g = 2.11 * kpa * 1000 * 1.3;
if (g < 450) { /*零点*/
return 0;
} else {
g -= 450;
}
g = filter(g);
// logger->info("g {}", g);
return g;
// kpa;
// lock_guard<recursive_mutex> lock(lock_);
// float kpa = m_pressure_sensor_data[1].value / 1000.0;
// int g = 2.11 * kpa * 1000 * 1.3;
// if (g < 450) { /*零点*/
// return 0;
// } else {
// g -= 450;
// }
// g = filter(g);
// // logger->info("g {}", g);
// return g;
}
int DeviceIoControlService::getPressureSensorData(int index) {
lock_guard<recursive_mutex> lock(lock_);
@ -458,6 +477,5 @@ bool DeviceIoControlService::getAllSensorData(DeviceIoControlService::all_h2o2se
return true;
}
void DeviceIoControlService::printerTest() {}
void DeviceIoControlService::printerPrintf(string str) { GET_SERVICE(UartPrinter)->print(ZIconv::utf8_to_gb2312(str)); }

14
src/service/device_io_control_service.hpp

@ -21,6 +21,10 @@
#include <mutex>
// std::lock_guard<std::recursive_mutex> lock(lock_);
//
#include "configs/gconfig.hpp"
#include "utils/moving_average_filter.hpp"
#include "utils/volume_convertor.hpp"
/**
* @brief
@ -62,6 +66,13 @@ class DeviceIoControlService : public enable_shared_from_this<DeviceIoControlSer
int32_t m_AirInletProportionalValve_state = 0;
int32_t m_AirOutletProportionalValve_state = 0;
unique_ptr<Thread> m_PressureSensorDataSampleThread;
shared_ptr<GConfig> m_config;
// 液体重量计算
int32_t m_disinfectantVolumeSample_g; // 消毒液量采样
VolumeConvertor m_volumeConvertor;
MovingAverageFilter m_DisinfectantWeightFilter = MovingAverageFilter(20);
public:
int32_t m_airCompressor_channelIndex = 0;
int32_t m_airCompressor_valve1State = 0;
@ -178,5 +189,8 @@ class DeviceIoControlService : public enable_shared_from_this<DeviceIoControlSer
} all_h2o2sensor_data_t;
virtual bool getAllSensorData(DeviceIoControlService::all_h2o2sensor_data_t& data);
private:
void updateDisinfectantVolumeSample(float _pa);
};
} // namespace iflytop

34
src/service/disinfection_ctl_service.cpp

@ -55,6 +55,8 @@ void DisinfectionCtrlService::initialize() {
m_deviceIoControlService->heartingPlate_setPower(false);
m_deviceIoControlService->airBlower_setState(false);
m_deviceIoControlService->airCompressor_setState(false);
m_dvalueComputer.initialize();
}
static string getTime() {
@ -96,37 +98,7 @@ static bool zfeq(float a, float b, float eps = 0.01) {
}
return false;
}
float DisinfectionCtrlService::getDisinfectionDValue(float ppm) {
/**
* @brief
*
* D值的计算公式是根据美国竞品的数据记录计算得来的
*
* 150,y=-0.5269X+97.868
* 150,y=-0.1405X+40.369
*/
if (zfeq(ppm, 0)) {
return -1;
}
float dvalue = 0;
if (ppm < 150) {
dvalue = -0.5251 * ppm + 98.154;
} else if (ppm >= 150 && ppm < 240) {
dvalue = -0.125 * ppm + 38.913;
} else if (ppm >= 240) {
// 240 -> 8.913
// 1400 -> 2
// y = -0.00603x + 10.4472
dvalue = -0.00596 * ppm + 10.3434;
}
if (dvalue < 2) {
dvalue = 2;
}
return dvalue;
}
float DisinfectionCtrlService::getDisinfectionDValue(float ppm) { return m_dvalueComputer.computeDValue(ppm); }
float DisinfectionCtrlService::computeNowLogLevel(DisinfectionContext& context) {
float dvalue = context.dvalue;
if (dvalue > 0) {

4
src/service/disinfection_ctl_service.hpp

@ -19,6 +19,7 @@
#include "iflytop/components/zcanreceiver/zcanhost.hpp"
#include "iflytop/core/core.hpp"
#include "service/device_io_control_service.hpp"
#include "utils/dvalue_computer.hpp"
#include "zservice_container/zservice_container.hpp"
/**
* @brief
@ -55,6 +56,8 @@ class DisinfectionCtrlService : public enable_shared_from_this<DisinfectionCtrlS
shared_ptr<DBService> m_dbService;
shared_ptr<DisinfectionLogsManager> m_disinfectionLogsManager;
DValueComputer m_dvalueComputer;
recursive_mutex lock_;
int m_disinfectionWorkState = 0;
@ -99,7 +102,6 @@ class DisinfectionCtrlService : public enable_shared_from_this<DisinfectionCtrlS
int continued_humi = 0;
shared_ptr<DisinfectionLogger> csvlogger;
};
public:

55
src/utils/dvalue_computer.cpp

@ -0,0 +1,55 @@
#include "dvalue_computer.hpp"
#include <cmath>
#include "zservice_container/zservice_container.hpp"
using namespace iflytop;
using namespace std;
static bool zfeq(float a, float b, float eps = 0.01) {
if (fabs(a - b) < eps) {
return true;
}
return false;
}
void DValueComputer::initialize() {
/**
* @brief
*/
m_config = GET_SERVICE(GConfig);
}
float DValueComputer::computeDValue(float h2o2ppm) {
/**
* @brief
*
* D值的计算公式是根据美国竞品的数据记录计算得来的
*
* 150,y=-0.5269X+97.868
* 150,y=-0.1405X+40.369
*/
if (zfeq(h2o2ppm, 0)) {
return -1;
}
float dvalue = 0;
if (h2o2ppm < 150) {
//
dvalue = -0.5251 * h2o2ppm + 98.154;
} else if (h2o2ppm >= 150 && h2o2ppm < 240) {
//
dvalue = -0.125 * h2o2ppm + 38.913;
} else if (h2o2ppm >= 240) {
//
dvalue = -0.00596 * h2o2ppm + 10.3434;
}
if (dvalue < 2) {
dvalue = 2;
}
dvalue = dvalue * m_config->get_dvalueCoefficient();
return dvalue;
}

16
src/utils/dvalue_computer.hpp

@ -0,0 +1,16 @@
#pragma once
#include <stdio.h>
#include "configs/gconfig.hpp"
namespace iflytop {
class DValueComputer {
ENABLE_LOGGER(DValueComputer);
shared_ptr<GConfig> m_config;
public:
void initialize();
float computeDValue(float h2o2ppm);
};
} // namespace iflytop

43
src/utils/moving_average_filter.hpp

@ -0,0 +1,43 @@
#pragma once
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <vector>
namespace iflytop {
using namespace std;
class MovingAverageFilter {
size_t size_;
float sum_ = 0;
std::list<float> values_;
public:
MovingAverageFilter(size_t size) : size_(size) {
if (size_ <= 0) {
throw std::invalid_argument("size must be greater than 0");
}
}
float filter(float value) {
if (values_.size() < size_) {
values_.push_back(value);
sum_ += value;
return sum_ / values_.size();
}
sum_ -= values_.front();
values_.pop_front();
values_.push_back(value);
sum_ += value;
return sum_ / size_;
}
private:
};
} // namespace iflytop

81
src/utils/volume_convertor.cpp

@ -0,0 +1,81 @@
#include "volume_convertor.hpp"
using namespace iflytop;
float VolumeConvertor::pa2high(float pa) {
/**
* @brief kpa
*
* p = h*density*g
*
* h = p/(density*g)
*
* p :, pa
* density:, kg/m^3
* g :,
* h :, m
*
* 30.5%=1.11331981022045g/cm^3 = 1113.31981022045kg/m^3
*
*/
// 计算液面高度
float h_m = pa / (density * 9.78); // 液体密度最后会被约掉,大小不影响结果
float h_dm = h_m * 10;
return h_dm;
}
/**
* @brief
*
* @param rb
* @param ru
* @param h
* @param nowh
* @return float
*/
float VolumeConvertor::computeConeVolume(float rb, float ru, float h, float nowh) {
if (nowh > h) nowh = h;
if (nowh < 0) nowh = 0;
float rb_now = rb + (ru - rb) * nowh / h;
float v = PI * nowh * (rb_now * rb_now + rb_now * ru + ru * ru) / 3;
return v;
}
float VolumeConvertor::pressurePa2VolumeG(float _pa) {
float pa = _pa - 90;
if (pa < 0) {
pa = 0;
}
// 计算液面高度
float h_dm = pa2high(pa);
float h1_dm = h_dm;
float h2_dm = h_dm - container_h1;
float h3_dm = h_dm - container_h2 - container_h1;
float h4_dm = h_dm - container_h3 - container_h2 - container_h1;
h1_dm = h1_dm < 0 ? 0 : h1_dm;
h2_dm = h2_dm < 0 ? 0 : h2_dm;
h3_dm = h3_dm < 0 ? 0 : h3_dm;
h4_dm = h4_dm < 0 ? 0 : h4_dm;
h1_dm = h1_dm > container_h1 ? container_h1 : h1_dm;
h2_dm = h2_dm > container_h2 ? container_h2 : h2_dm;
h3_dm = h3_dm > container_h3 ? container_h3 : h3_dm;
h4_dm = h4_dm > container_h4 ? container_h4 : h4_dm;
// printf("h_dm:%f h1_dm:%f, h2_dm:%f, h3_dm:%f, h4_dm:%f\n",h_dm, h1_dm, h2_dm, h3_dm, h4_dm);
float v1 = computeConeVolume(container_rb1, container_ru1, container_h1, h1_dm);
float v2 = computeConeVolume(container_rb2, container_ru2, container_h2, h2_dm);
float v3 = computeConeVolume(container_rb3, container_ru3, container_h3, h3_dm);
float v4 = computeConeVolume(container_rb4, container_ru4, container_h4, h4_dm);
// printf("v1:%f, v2:%f, v3:%f, v4:%f\n", v1, v2, v3, v4);
// h4_dm * (double)(2.1124069002737764)
float V_L = v1 + v2 + v3 + v4; // 0.001m^3
float g = V_L * density; // 1m^3 = 1000L
return g;
}

69
src/utils/volume_convertor.hpp

@ -0,0 +1,69 @@
#pragma once
#include <stdio.h>
namespace iflytop {
#define PI 3.14159265358979323846
class VolumeConvertor {
/**
* @brief
*
* | <--r4_2 -->|
* _____________
* | |
* | |
* | | h4
* | |
* | r4_1 |
* \ / h3
* | | h2
* \ _____ / h1
*
*
* | ru |
* -----------
* \ /
* \ / h
* \_____/
* |rb|
*
*/
float container_h4 = 1.83;
float container_ru4 = 0.64;
float container_rb4 = 0.64;
float container_h3 = 0.17;
float container_ru3 = 0.64;
float container_rb3 = 0.47;
float container_h2 = 0.0737;
float container_ru2 = 0.47;
float container_rb2 = 0.47;
float container_h1 = 0.0376;
float container_ru1 = 0.47;
float container_rb1 = 0.04;
float density = 1000; // kg/m^3
public:
float pressurePa2VolumeG(float _pa);
private:
float pa2high(float pa);
/**
* @brief
*
* @param rb
* @param ru
* @param h
* @param nowh
* @return float
*/
float computeConeVolume(float rb, float ru, float h, float nowh);
};
} // namespace iflytop

2
src/version.hpp

@ -1,2 +1,2 @@
#pragma once
#define VERSION "pipeline_disinfection_1.0"
#define VERSION "1.2"
Loading…
Cancel
Save