ljljlj 发表于 2024-2-27 19:42:17

【开源】全工位氢氧根离子检测站





一.简介
    本开源项目一个用于检测水中离子含量的工作站,主要是氢氧根离子,根据反性原则,也可以得到大致的H+离子浓度,这里的测检水可以分为多种的,通常情况下可用于电厂污水, 纺织污水, 池塘污水等等,根据检测到的离子浓度做出及时防护措施,以往检测人员比较辛苦,
都是通过人工采样后,然后再接着人工化学试剂的方式来分析离子浓度,这样的做法费时费力而且有时候精度差,不能很好的批量化检测,而全工位氢氧根离子检测站就是基于此需求而诞生的一款自动化全工位设备.简化了人力,大大的加快效率,它有如下特点:
1.具有全工位效率,默认为1-40工位,可以搭配多阶延长板实现外扩到1-120工位
2.具有工位多兼容性,工位的大小可以手动调节,支持宽瓶, 窄瓶, 小试管, 长试管等等
3.配置三轴机械爪,实现全工位范围内的移动, 搅拌,浸泡, 测量等操作
4.具有6级测量精度可选择,当选为自动档时,系统自动预判
5.支持多点离子校准,点数是任意的,不强制,不固定
6.仪器运行状态,以及校准状态详细展示
7.起始工位,工位数量可以任意设置,但不能跳点
硬件上有rs485, rs232双接口,配合modbus协议和私有协议实现对接各路外机


二.GUI工程


图标素材


图片素材

DGUS tool等界面












三.C51工程

机械臂核心操作代码
#ifndef __BASE_H__
#define __BASE_H__
#include "sys.h"

#define BASE_SHAKE_CNT_DEF                        12
#define BASE_CLEAN_TIME_DEF                        3

u8 base_shake(u16 cnt,u16 quit_code);
u8 base_clean(u16 clean_time, u16 quit_code);
u8 base_air_dry(u16 quit_code);
u8 base_select_sample(u8 pos,u8 is_clean,u16 quit_code);


#include "base.h"
#include "motor.h"
#include "test.h"
#include "params.h"












u8 base_shake_x_or_y(u8 is_x,u16 cnt,u16 quit_code)
{
      #define SHAKE_STEP                        300
      #define SHAKE_DELAY                        400
      s16 cur_step = 0;
      u8 res = 0;
      
      if(cur_motor_pos==MOTOR_POS_CLEAN)
                return 0;
      
      while(cnt--)
      {
                if(cur_step==0)
                        cur_step = SHAKE_STEP;
                else if(cur_step>0)
                        cur_step = SHAKE_STEP*-2;
                else
                        cur_step = SHAKE_STEP*2;
                if(is_x)
                {
                        motor_set_dir((cur_step<0?MOTOR_DIR_FORWARD:MOTOR_DIR_BACKWARD),MOTOR_DIR_SKIP,MOTOR_DIR_SKIP);
                        motor_move((cur_step<0?-cur_step:cur_step),0,0);
                }else
                {
                        motor_set_dir(MOTOR_DIR_SKIP,(cur_step<0?MOTOR_DIR_FORWARD:MOTOR_DIR_BACKWARD),MOTOR_DIR_SKIP);
                        motor_move(0,(cur_step<0?-cur_step:cur_step),0);                        
                }
                sys_delay_ms(SHAKE_DELAY);
                if(func_code_scan()==quit_code)
                {
                        res = 1;
                        break;
                }      
      }
      
      if(cur_step!=0)
      {
                if(is_x)
                {
                        motor_set_dir((cur_step<0?MOTOR_DIR_BACKWARD:MOTOR_DIR_FORWARD),MOTOR_DIR_SKIP,MOTOR_DIR_SKIP);
                        motor_move(SHAKE_STEP,0,0);
                }else
                {
                        motor_set_dir(MOTOR_DIR_SKIP,(cur_step<0?MOTOR_DIR_BACKWARD:MOTOR_DIR_FORWARD),MOTOR_DIR_SKIP);
                        motor_move(0,SHAKE_STEP,0);                        
                }
                sys_delay_ms(SHAKE_DELAY);
      }
      
      return res;
}






u8 base_shake(u16 cnt,u16 quit_code)
{
      if(base_shake_x_or_y(1,cnt,quit_code))
                return 1;
      if(base_shake_x_or_y(0,cnt,quit_code))
                return 2;
      
      return 0;
}






u8 base_clean(u16 clean_time, u16 quit_code)
{
      #define FULL_TIME                        (sys_params.full_time)
      #define EMPTY_TIME                (FULL_TIME+25)
      #define BASE_UNIT                        200
      u8 res = 0;
      u8 time;
      
      


      motor_select_sample(MOTOR_POS_CLEAN);
      
      WASTE_PUMP_OFF();
      WATER_PUMP_ON();
      time = FULL_TIME;
      while(time--)
      {
                sys_delay_ms(BASE_UNIT);
                if(func_code_scan()==quit_code)
                {
                        res = 1;
                        break;
                }
      }
      


      if(clean_time)
      {
                WASTE_PUMP_ON();
                while(clean_time--)
                {
                        sys_delay_ms(1000);
                        if(func_code_scan()==quit_code)
                        {
                              res = 1;
                              break;
                        }
                }               
      }
      


      WASTE_PUMP_ON();
      WATER_PUMP_OFF();
      time = EMPTY_TIME;
      while(time--)
      {
                sys_delay_ms(BASE_UNIT);
                if(func_code_scan()==quit_code)
                        res = 3;
      }               
      WASTE_PUMP_OFF();


      if(res==0)
      {
                test_update_sta(WORK_STA_AIR_DRY);
                res = base_air_dry(quit_code);
      }
      
      return res;
}






u8 base_air_dry(u16 quit_code)
{
      #define AIR_DRY_TIME      (sys_params.air_dry_time)
      u8 res = 0;
      u8 sec;
      
      AIR_PUMP_ON();
      sec = AIR_DRY_TIME;
      while(sec--)
      {
                sys_delay_ms(1000);
                if(func_code_scan()==quit_code)
                {
                        res = 1;
                        break;
                }
      }      
      AIR_PUMP_OFF();
      
      return res;
}






u8 base_select_sample(u8 pos,u8 is_clean,u16 quit_code)
{


      if(is_clean)
      {
                test_update_sta(WORK_STA_CLEAN);
                if(is_testing)
                {
                        work_sta = WORK_STA_TEST_STEP_1;
                        if(test_upload_data())
                              return 1;
                }
                if(base_clean(BASE_CLEAN_TIME_DEF, quit_code))
                        return 1;
      }
      if(is_testing)
      {
                work_sta = WORK_STA_TEST_STEP_2;
                if(test_upload_data())
                        return 1;
      }      
      
      test_update_sta(WORK_STA_MOVE);
      motor_select_sample(pos);
      if(func_code_scan()==quit_code)
                return 2;


      test_update_sta(WORK_STA_SHAKE);
      if(base_shake(BASE_SHAKE_CNT_DEF,quit_code))
                return 3;
      if(func_code_scan()==quit_code)
                return 4;      
      
      return 0;
}


测试相关的代码

bit is_complete_tip = 0;
u16 complete_tip_time = 0;
u8 cur_bottle_no = 0;
u8 cur_completed_num = 0;
u8 total_sample_num = NUM_OF_GROUP_DEF;
u8 cur_work_sta = WORK_STA_IDLE;
u8 last_result = {"--------\0\0"};
u8 is_testing = 0;
u8 is_normal_completed = 0;

u8 test_make(u16 quit_code);

//开始测试
void test_start(u16 quit_code)
{
      u16 val;
      
      is_testing = 1;
      is_complete_tip = 0;
      cur_work_sta = WORK_STA_CLEAN;
      cur_completed_num = 0;
      cur_bottle_no = start_bottle_no;
      score = SCORE_UNKNOW;
      val = 1;
      sys_write_vp(MAIN_WIN_START_BTN_VP,(u8*)&val,1);
      main_win_update();
      
      
      is_normal_completed = !test_make(quit_code);
      if(is_normal_completed)
      {
                test_update_sta(WORK_STA_CLEAN);
                base_clean(BASE_CLEAN_TIME_DEF, quit_code);
      }
      motor_select_sample(MOTOR_POS_PROTECT);
      
      
      cur_work_sta = (is_normal_completed?WORK_STA_ALL_COMPLETED:WORK_STA_IDLE);
      cur_bottle_no = 0;
      val = 0;
      sys_write_vp(MAIN_WIN_START_BTN_VP,(u8*)&val,1);
      main_win_update();
      if(is_normal_completed)
      {
                is_complete_tip = 1;
                complete_tip_time = COMPLETE_TIP_MAX_TIME;
                sys_goto_win(WIN_ID_MAIN);
                sys_delay_ms(100);
                sys_click_pos(2,13);
      }
      is_testing = 0;
      is_stable = 0;
      check_stable_tick = 0;
      val = 0;
      sys_write_vp(BTN_VAL_ADDR,(u8*)&val,1);
      work_sta = WORK_STA_TEST_STEP_COMPLETED;
      test_upload_data();
}


//测试流程
u8 test_make(u16 quit_code)
{
      u8 pos;
      u8 offset;
      float sum = 0;
      float max = -999999;
      float min = 999999;
      u8 index = 0;
      u8 end_pos;
      
      end_pos = total_sample_num+start_bottle_no-1;
      for(pos=(start_bottle_no-1);pos<end_pos;pos++)
      {
               
                if(base_select_sample(pos,!(is_group&&(index%num_of_group)),quit_code))
                        return 1;
               
                cur_work_sta = WORK_STA_ANALYSIS;
                main_win_update();
                if(is_testing)
                {
                        work_sta = WORK_STA_TEST_STEP_3;
                        if(test_upload_data())
                              return 1;
                }
                check_stable_tick = 1;
                is_stable = 0;
                stable_val = 999999;
                while(1)
                {
                        if(is_stable)
                              break;
                        if(func_code_scan()==quit_code)
                              return 2;
                }
               
                score = SCORE_UNKNOW;
                memset(last_result,0,LAST_RESULT_MAX_LEN);
                sprintf(last_result,"%.3f",cur_ph);
                if(is_group&&(invalid_num_of_group<num_of_group))
                {
                        offset = index%num_of_group;
                        if(offset>=invalid_num_of_group)
                        {
                              sum += cur_val;//对有效点累加求和
                              if(cur_val>max)
                                        max = cur_val;
                              if(cur_val<min)
                                        min = cur_val;
                        }
                        if((offset+1)==num_of_group)
                        {
                              sum /= (num_of_group-invalid_num_of_group);
                              score = ((max-min)<valid_range_of_group?SCORE_YES:SCORE_NO);
                              sum = 0;
                              max = -999999;
                              min = 999999;
                        }               
                }
                cur_completed_num++;
                if(is_testing)
                {
                        work_sta = WORK_STA_TEST_STEP_4;
                        if(test_upload_data())
                              return 1;
                }
                cur_bottle_no++;
                if(cur_bottle_no>end_pos)
                        cur_bottle_no = 0;
                main_win_update();
                index++;
      }
      
      return 0;
}




四,视频演示效果
视频入口











页: [1]
查看完整版本: 【开源】全工位氢氧根离子检测站