|
|
#include "manage.h"
|
|
|
#include "var.h"
|
|
|
#include "ops.h"
|
|
|
#include "log.h"
|
|
|
#include "test.h"
|
|
|
#include "user.h"
|
|
|
#include "config.h"
|
|
|
#include "matrix.h"
|
|
|
#include "control.h"
|
|
|
|
|
|
using std::pair;
|
|
|
|
|
|
//CManage类
|
|
|
|
|
|
void makelenstr(char* psz, int len)
|
|
|
{
|
|
|
int nlen = strlen(psz);
|
|
|
if (nlen < len)
|
|
|
{
|
|
|
mem_backward(psz, nlen, len - nlen);
|
|
|
for (int i = 0; i < len - nlen; i++)
|
|
|
{
|
|
|
psz[i] = '0';
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CManage::UpdateVarProduct()
|
|
|
{
|
|
|
ZERO_CHK(m_bupdatevar);
|
|
|
|
|
|
CProduct* p = NULL;
|
|
|
char buff[256] = { 0 };
|
|
|
for (int i = 0; i < m_vacm_cnt; i++)
|
|
|
{
|
|
|
p = m_vacm_lst[i];
|
|
|
if (p)
|
|
|
{
|
|
|
makelenstr(p->data.sn, 4);
|
|
|
sprintf(buff, "0 %s %d %d %d time:%s status:%d count:%d",
|
|
|
p->data.sn, p->_t1, p->_t2, p->_t3,
|
|
|
p->data.start, p->data.status, p->data.count);
|
|
|
}
|
|
|
else sprintf(buff, "%d", 0);
|
|
|
if (strcmp(buff, m_pvar_vacm[i]->getcs()))
|
|
|
{
|
|
|
m_pvar_vacm[i]->sets(buff);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < TESTCNT; i++)
|
|
|
{
|
|
|
p = m_ptest[i]->_p;
|
|
|
if (p)
|
|
|
{
|
|
|
makelenstr(p->data.sn, 4);
|
|
|
sprintf(buff, "%d %s %d %d %d time:%s status:%d count:%d",
|
|
|
m_ptest[i]->_data.status, p->data.sn, p->_t1, p->_t2,
|
|
|
p->_t3, p->data.start, p->data.status, p->data.count);
|
|
|
}
|
|
|
else sprintf(buff, "%d", m_ptest[i]->_data.status);
|
|
|
if (strcmp(buff, m_pvar_test[i]->getcs()))
|
|
|
{
|
|
|
m_pvar_test[i]->sets(buff);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int CManage::Test(const char* pszcmd)
|
|
|
{
|
|
|
char name[32] = { 0 };
|
|
|
char desc[32] = { 0 };
|
|
|
|
|
|
for (int i = 0; i < m_vacm_cnt; i++)
|
|
|
{
|
|
|
sprintf(name, "vacm%d_p", i + 1);
|
|
|
sprintf(desc, "吸嘴%d产品数据", i + 1);
|
|
|
m_pvar_vacm[i] = getVar(name, desc);
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < TESTCNT; i++)
|
|
|
{
|
|
|
sprintf(name, "test%d_p", i + 1);
|
|
|
sprintf(desc, "治具%d产品数据", i + 1);
|
|
|
m_pvar_test[i] = getVar(name, desc);
|
|
|
}
|
|
|
m_bupdatevar = true;
|
|
|
/*CoreConfig cfg;
|
|
|
GetConfig(&cfg);
|
|
|
cfg.bBindB = 1;
|
|
|
cfg.idualindex = 3;
|
|
|
cfg.bPassTestB = 1;
|
|
|
SetConfig(&cfg);*/
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::GetVacmCount()
|
|
|
{//获取吸嘴现在有多少颗物料
|
|
|
int count = 0;
|
|
|
for(int i = 0; i < m_vacm_cnt; i++)
|
|
|
{
|
|
|
if (m_vacm_lst[i]) count++;
|
|
|
}
|
|
|
return count;
|
|
|
}
|
|
|
|
|
|
void CManage::MakeDate(char* pszdate)
|
|
|
{
|
|
|
SYS_TIME tm;
|
|
|
sys_GetLocalTime(&tm);
|
|
|
sprintf(pszdate, "%04d/%02d/%02d %02d:%02d:%02d",
|
|
|
tm.wYear, tm.wMonth, tm.wDay,
|
|
|
tm.wHour, tm.wMinute, tm.wSecond);
|
|
|
}
|
|
|
|
|
|
int CManage::M1()
|
|
|
{//M1 通知进料仓拍照,并返回拍照结果
|
|
|
return m_pVision[EVInput]->Process();
|
|
|
}
|
|
|
|
|
|
int CManage::M3()
|
|
|
{//M1 通知OK仓拍照,并返回拍照结果
|
|
|
return m_pVision[EVOkTray]->Process();
|
|
|
}
|
|
|
|
|
|
int CManage::M4()
|
|
|
{//M4 通知NG仓拍照,并返回拍照结果
|
|
|
return m_pVision[EVNGTray]->Process();
|
|
|
}
|
|
|
|
|
|
int CManage::M2()
|
|
|
{//M2 通知2号相机拍照,并返回拍照结果
|
|
|
return m_pVision[EVHamal]->Process();
|
|
|
}
|
|
|
|
|
|
int CManage::M5()
|
|
|
{//NG取一拍一
|
|
|
return m_pVision[EVNGTakeOne]->Process();
|
|
|
}
|
|
|
|
|
|
int CManage::M6()
|
|
|
{//NG放一拍一
|
|
|
return m_pVision[EVNGPutOne]->Process();
|
|
|
}
|
|
|
|
|
|
int CManage::M7()
|
|
|
{//治具取
|
|
|
return m_pVision[EVTestTake]->Process();
|
|
|
}
|
|
|
|
|
|
int CManage::M8()
|
|
|
{//治具放
|
|
|
return m_pVision[EVTestPut]->Process();
|
|
|
}
|
|
|
|
|
|
int CManage::VacmReset()
|
|
|
{//vacmreset 通知释放吸嘴产品数据
|
|
|
_logct = 0;
|
|
|
for(int i = 0; i < m_vacm_cnt; i++)
|
|
|
{
|
|
|
m_vacm_lst[i] = NULL;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::SimTest(int tindex, int benable)
|
|
|
{
|
|
|
CoreConfig cfg;
|
|
|
memcpy(&cfg, &m_cfg, sizeof(cfg));
|
|
|
switch(tindex)
|
|
|
{
|
|
|
case 1:
|
|
|
cfg.bSimTest1 = benable;
|
|
|
break;
|
|
|
case 2:
|
|
|
cfg.bSimTest2 = benable;
|
|
|
break;
|
|
|
case 3:
|
|
|
cfg.bSimTest3 = benable;
|
|
|
break;
|
|
|
case 4:
|
|
|
cfg.bSimTest4 = benable;
|
|
|
break;
|
|
|
case 5:
|
|
|
cfg.bSimTest5 = benable;
|
|
|
break;
|
|
|
case 6:
|
|
|
cfg.bSimTest6 = benable;
|
|
|
break;
|
|
|
default:
|
|
|
return -1;
|
|
|
}
|
|
|
return SetConfig(&cfg);
|
|
|
}
|
|
|
|
|
|
int CManage::StockReset(int sindex)
|
|
|
{//stockreset sindex 通知释放料盘产品数据 sindex料仓编号[1-5]
|
|
|
vector<CProduct*>::iterator it;
|
|
|
|
|
|
RETURN_CHK_NOPRT(sindex >= LocationInput && sindex <= LocationNg3, ERR_INPUT_PARAM);
|
|
|
|
|
|
vector<CProduct*>& vec = m_vecStock[sindex - LocationInput];
|
|
|
for (it = vec.begin(); it != vec.end(); it++)
|
|
|
{
|
|
|
if (*it)
|
|
|
{//有值则释放
|
|
|
FreeProduct(*it);
|
|
|
*it = NULL;
|
|
|
}
|
|
|
}
|
|
|
//不清空内存 pvec->clear();
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::VacmTake()
|
|
|
{//vacmtake 通知设置需要取料的吸嘴编号为0时无效,设置到变量'v'中
|
|
|
int count = GetVacmCount();
|
|
|
if (count >= m_vacm_cnt - 1 || m_pclear->geti())
|
|
|
{//已满或者有清料信号
|
|
|
m_pv->seti(0);
|
|
|
m_pt->seti(0);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
for(int i = 0; i < m_vacm_cnt; i++)
|
|
|
{
|
|
|
if (!m_vacm_lst[i])
|
|
|
{
|
|
|
count = i + 1;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_pt->seti(1);
|
|
|
m_pv->seti(count);
|
|
|
LOG_INF1("input set v = %d", count);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::FindTest(CProduct* p, bool bchkp, int aend)
|
|
|
{//查找可以放的治具
|
|
|
for (int i = 0; i < aend; i++)
|
|
|
{//测试治具
|
|
|
if (bchkp && m_ptest[i]->_p) continue; //检测有料
|
|
|
if (!m_ptest[i]->Enabled()) continue; //未启用
|
|
|
if (!m_ptest[i]->IsReady()) continue; //不在就绪状态
|
|
|
if (m_ptest[i]->IsNextNoTest())
|
|
|
{//用于缓存 -- 直接可以
|
|
|
REPORT("set notest t = %d.", i + 1);
|
|
|
//set_int_var("test", 1);
|
|
|
//ops_analog_signal(IOS_PAUSE, 1); //测试,暂停一下
|
|
|
return i + 1;
|
|
|
}
|
|
|
if (IsAAB() && !p->CanTestAAB(m_ptest[i]->_data.ate))
|
|
|
{//AAB模式不可以放
|
|
|
continue;
|
|
|
}
|
|
|
if (IsABC() && !p->CanTestABC(m_ptest[i]->_data.ate))
|
|
|
{//ABC模式不可以放
|
|
|
continue;
|
|
|
}
|
|
|
return i + 1; //ok直接返回
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void CManage::GetPutByTest(int &v, int t, bool bchkp)
|
|
|
{//testput 通知设置需要进入治具的吸嘴编号->'v',治具编号->'t',为0时无效
|
|
|
int aend = m_pEnda->geti();
|
|
|
const char* ate = m_ptest[t-1]->_data.ate;
|
|
|
|
|
|
for(int i = 0; i < m_vacm_cnt; i++)
|
|
|
{//吸嘴编号
|
|
|
if (!m_vacm_lst[i]) continue;
|
|
|
if (bchkp && m_ptest[t - 1]->_p) continue;
|
|
|
if (m_ptest[t - 1]->IsNextNoTest())
|
|
|
{//用于缓存 -- 直接可以
|
|
|
v = i + 1;
|
|
|
REPORT("set notest v = %d t = %d.", v, t);
|
|
|
//set_int_var("test", 1);
|
|
|
//ops_analog_signal(IOS_PAUSE, 1); //测试,暂停一下
|
|
|
break;
|
|
|
}
|
|
|
if (m_vacm_lst[i]->lastIndex() > aend) continue; //已经进B组测试
|
|
|
if (!m_vacm_lst[i]->NeedTest(getBinA())) continue; //不需要测试
|
|
|
if (IsAAB() && !m_vacm_lst[i]->CanTestAAB(ate))
|
|
|
{//AAB模式不可以放
|
|
|
continue;
|
|
|
}
|
|
|
if (IsABC() && !m_vacm_lst[i]->CanTestABC(ate))
|
|
|
{//ABC模式不可以放
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
v = i + 1;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CManage::GetTestPut(int &v, int &t, bool bchkp)
|
|
|
{//testput 通知设置需要进入治具的吸嘴编号->'v',治具编号->'t',为0时无效
|
|
|
v = 0;
|
|
|
if (t > 0 && t <= TESTCNT &&
|
|
|
m_ptest[t-1]->Enabled() &&
|
|
|
m_ptest[t-1]->IsReady())
|
|
|
{//治具编号有效
|
|
|
return GetPutByTest(v, t, bchkp);
|
|
|
}
|
|
|
|
|
|
for(int i = 0; i < m_vacm_cnt; i++)
|
|
|
{//吸嘴编号
|
|
|
if (!m_vacm_lst[i]) continue;
|
|
|
if (!m_vacm_lst[i]->NeedTest(getBinA())) continue; //不需要测试
|
|
|
t = FindTest(m_vacm_lst[i], bchkp);
|
|
|
if (0 == t) continue; //未找到
|
|
|
v = i + 1;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int CManage::TestPut()
|
|
|
{//testput 通知设置需要进入治具的吸嘴编号->'v',治具编号->'t',为0时无效
|
|
|
int v = 0;
|
|
|
int t = m_pt->geti(); //优先选择当前治具
|
|
|
int aend = m_pEnda->geti();
|
|
|
|
|
|
//GetTestPut(v, t, true);
|
|
|
GetTestPutDual(v, t, aend, true); //这里要判定有没有产品在治具
|
|
|
m_pv->seti(v && t ? v : 0);
|
|
|
m_pt->seti(v && t ? t : 0);
|
|
|
LOG_INF1("testput get v = %d t = %d", v, t);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void CManage::GetTestTake(int &v, int &t)
|
|
|
{//testake 通知设置需要从治具取料的吸嘴编号->'v',治具编号->'t',为0时无效
|
|
|
v = 0; //先获取空闲的吸嘴
|
|
|
for(int i = 0; i < m_vacm_cnt; i++)
|
|
|
{//吸嘴编号
|
|
|
if (m_vacm_lst[i]) continue; //已有料
|
|
|
v = i + 1;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
ZERO_CHK(v > 0);
|
|
|
|
|
|
if (t > 0 && t <= TESTCNT &&
|
|
|
m_ptest[t-1]->Enabled() && //启用
|
|
|
m_ptest[t-1]->IsReady()) //就绪
|
|
|
{//当前传入的治具编号有效,直接返回
|
|
|
if (!m_ptest[t - 1]->_p)
|
|
|
{//如果是无料,则此次取料作废,不取直接放
|
|
|
v = 0; //这里不可以把t变0,会影响后面的放料
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
t = 0; //重置
|
|
|
for(int i = 0; i < TESTCNT; i++)
|
|
|
{//测试治具
|
|
|
if (!m_ptest[i]->_p) continue; //没料
|
|
|
if (!m_ptest[i]->Enabled()) continue; //未启用
|
|
|
if (!m_ptest[i]->IsReady()) continue; //未就绪
|
|
|
t = i + 1;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int CManage::TestTake()
|
|
|
{//testake 通知设置需要从治具取料的吸嘴编号->'v',治具编号->'t',为0时无效
|
|
|
int v = 0;
|
|
|
int t = m_pt->geti(); //优先选择当前治具
|
|
|
|
|
|
GetTestTake(v, t);
|
|
|
m_pt->seti(t);
|
|
|
m_pv->seti(v && t ? v : 0);
|
|
|
LOG_INF1("testake get v = %d t = %d", v, t);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::StockPut()
|
|
|
{//stockput 通知设置需要放回料仓的吸嘴编号->'v',料仓编号[2-5]->'t',为0时无效
|
|
|
int v = 0;
|
|
|
int t = 0;
|
|
|
int tmax = 0;
|
|
|
int vmax = 0;
|
|
|
|
|
|
for(int i = 0; i < m_vacm_cnt; i++)
|
|
|
{//查找最大值
|
|
|
if (!m_vacm_lst[i]) continue; //无料
|
|
|
if (m_vacm_lst[i]->lastIndex() <= m_pEnda->geti() //未进B组
|
|
|
&& m_vacm_lst[i]->NeedTest(getBinA())) continue; //且A组需要测试
|
|
|
v = i + 1;
|
|
|
t = m_vacm_lst[i]->IsOk() ? 2/*m_vacm_lst[i]->tCount() + 1*/ : 5; //3次NG为料仓5
|
|
|
if (t > tmax)
|
|
|
{//找到更大值 -- 每个料仓一次性放完
|
|
|
tmax = t;
|
|
|
vmax = v;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_pv->seti(vmax);
|
|
|
m_pt->seti(tmax);
|
|
|
if (vmax > 0) m_pBin->sets(m_vacm_lst[vmax - 1]->data.level); //设置bin信息到变量
|
|
|
LOG_INF1("stockput set v = %d t = %d", vmax, tmax);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void CManage::GetNotestPut(int &v, int &t)
|
|
|
{//4个吸嘴都需要测试,但是又找不到治具可以测试,这个时候卡死
|
|
|
//for (int i = 0; i < m_vacm_cnt; i++)
|
|
|
//{
|
|
|
// if (m_vacm_lst[i])
|
|
|
// {//有物料的吸嘴就行
|
|
|
// v = i + 1;
|
|
|
// break;
|
|
|
// }
|
|
|
//}
|
|
|
v = 1; //理论上应该是这样
|
|
|
for (int i = 0; i < TESTCNT; i++)
|
|
|
{//测试治具
|
|
|
if (m_ptest[i]->_p) continue; //有料
|
|
|
if (!m_ptest[i]->Enabled()) continue; //未启用
|
|
|
if (!m_ptest[i]->IsReady()) continue; //未就绪
|
|
|
m_ptest[i]->setNextNoTest(); //设置为不测试
|
|
|
t = i + 1;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#define PUTCT 6000 //补料时间 每颗6s
|
|
|
|
|
|
int CManage::WhereToGo()
|
|
|
{//where 通知设置当前是给治具换料还是放料到料仓,设置到变量't'中,0标识放料到料仓,[1-6]标识给治具换料
|
|
|
int i = 0;
|
|
|
int v = 0;
|
|
|
int t = 0;
|
|
|
int v1 = 0;
|
|
|
int t1 = 0;
|
|
|
ulong cur = 0;
|
|
|
ulong minct = TESTCT; //最小时间
|
|
|
ulong takect = 0; //补料需要时间
|
|
|
ulong tm = 0; //测试结束剩余时间
|
|
|
int ntest = 0; //有多少个可以放到治具的料
|
|
|
int nput = 0; //有多少个可以放到OK料仓的料
|
|
|
int nstock = 0; //有多少个可以放到料仓的料
|
|
|
//int curt = m_pt->geti(); //当前治具序号
|
|
|
int curt = m_prePut; //当前治具序号
|
|
|
int aend = m_pEnda->geti();
|
|
|
int bclear = m_pclear->geti(); //清料信号
|
|
|
|
|
|
for(i = 0; i < m_vacm_cnt; i++)
|
|
|
{
|
|
|
if (!m_vacm_lst[i])
|
|
|
{//空的吸嘴先记录一下
|
|
|
if (0 == v) v = i + 1;
|
|
|
continue;
|
|
|
}
|
|
|
if (NeedTestDual(m_vacm_lst[i]))
|
|
|
{//次数小于3次并且测试NG
|
|
|
ntest++;
|
|
|
}
|
|
|
else
|
|
|
{//必须放到料仓
|
|
|
nstock++;
|
|
|
if (1 == m_vacm_lst[i]->tCount()) nput++; //OK仓
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_pnput->seti(nput);
|
|
|
m_pntake->seti(m_vacm_cnt - ntest - 1);
|
|
|
//if ((0 == ntest && !bclear) || (ntest + nstock == m_vacm_cnt))
|
|
|
if ((0 == ntest && !bclear)
|
|
|
|| (nstock >= m_vacm_cnt - 1)
|
|
|
|| (nstock > 0 && ntest + nstock >= m_vacm_cnt))
|
|
|
{//吸嘴上没有料,则必须放料 -- 大于2颗料要放仓库,则先放仓库
|
|
|
m_pt->seti(0);
|
|
|
LOG_INF1("where set t = 0");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
//计算当前放料到治具需要等多久?
|
|
|
//计算当前取满3颗料需要多久?
|
|
|
cur = sys_GetTickCount();
|
|
|
takect = PUTCT * nstock; //补料耗时预估
|
|
|
if (curt <= 0 || curt > TESTCNT) curt = TESTCNT;
|
|
|
i = curt - 1; //当前索引
|
|
|
do
|
|
|
{//从当前t下一个开始遍历,到下一次到t结束
|
|
|
i = (i + 1) % TESTCNT; //循环控制
|
|
|
if (!m_ptest[i]->Enabled()) continue; //未启用
|
|
|
if (m_ptest[i]->IsReady())
|
|
|
{//就绪状态直接放
|
|
|
t1 = i + 1;
|
|
|
//GetTestPut(v, t); //获取可以放的治具和吸嘴
|
|
|
//REPORT("test(%d) idle", t1);
|
|
|
GetTestPutDual(v1, t1, aend, ntest == m_vacm_cnt ? true : false); //获取可以放的治具和吸嘴
|
|
|
if (v1 > 0 && t1 > 0)
|
|
|
{//ok 可以换料
|
|
|
m_pv->seti(v); //吸嘴设置为取料吸嘴
|
|
|
m_pt->seti(t1);
|
|
|
LOG_INF1("where set v = %d t = %d", v, t1);
|
|
|
return 0;
|
|
|
}
|
|
|
if (bclear)
|
|
|
{//若没有可放的,但是有清料信号,判断是否可以取
|
|
|
GetTestTake(v1, t1);
|
|
|
if (v1 > 0 && t1 > 0)
|
|
|
{//ok 可以换料
|
|
|
m_pv->seti(v1);
|
|
|
m_pt->seti(t1);
|
|
|
LOG_INF1("where set v = %d t = %d", v1, t1);
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else if ((i < aend || bclear) && m_ptest[i]->IsRunning())
|
|
|
{//还需要多久可以测试完成(预估) -- A组才预估,B组必须空闲(清料时要等待)
|
|
|
tm = m_ptest[i]->startCT() + m_ptest[i]->lastCT();
|
|
|
if (tm > cur) tm -= cur; //剩余时间
|
|
|
else tm = 0; //即将结束
|
|
|
//REPORT("test(%d) lastct:%d start:%d remain time:%d", i + 1, m_ptest[i]->lastCT(), m_ptest[i]->startCT(), tm);
|
|
|
if (tm < minct)
|
|
|
{//获取最快结束测试的治具序号
|
|
|
minct = tm;
|
|
|
t = i + 1;
|
|
|
}
|
|
|
}
|
|
|
} while (i != curt - 1);
|
|
|
|
|
|
if (TESTCT == minct && bclear)
|
|
|
{//清料状态下,所有治具都已空
|
|
|
t = -1; //结束标识
|
|
|
m_prePut = 0;
|
|
|
REPORT("clear material finished.");
|
|
|
}
|
|
|
else if (minct > takect && nstock > 0)
|
|
|
{//取料比较快,并且还可以补料
|
|
|
t = 0;
|
|
|
}
|
|
|
else if (ntest == m_vacm_cnt)
|
|
|
{//4个吸嘴都需要测试,但是又找不到治具可以测试,这个时候卡死
|
|
|
GetNotestPut(v, t);
|
|
|
//m_pPause->seti(1); //暂停
|
|
|
REPORT("4 vacm must test.");
|
|
|
//send_message(MSG_NORMAL, "4 vacm must test.");
|
|
|
}
|
|
|
m_pv->seti(v);
|
|
|
m_pt->seti(t);
|
|
|
LOG_INF1("where set v = %d t = %d", v, t);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::TakeFromInput(const char* sn, int vacmIndex)
|
|
|
{//从进料盘取料
|
|
|
int index = 0;
|
|
|
CProduct* p = NULL;
|
|
|
|
|
|
RETURN_CHK_NOPRT(sn && *sn, ERR_INPUT_PARAM);
|
|
|
RETURN_CHK_NOPRT(strlen(sn) < MAX_NAME_LEN, ERR_INPUT_PARAM);
|
|
|
RETURN_CHK_NOPRT(vacmIndex > 0 && vacmIndex <= m_vacm_cnt, ERR_INPUT_PARAM);
|
|
|
RETURN_CHK_NOPRT(!m_vacm_lst[vacmIndex - 1], ERR_EXIST_PRODUCT);
|
|
|
|
|
|
sys_EnterCriticalSection(m_hSection);
|
|
|
p = GetFromInput();
|
|
|
strcpy(p->data.sn, sn);
|
|
|
MakeDate(p->data.start);
|
|
|
p->data.index = vacmIndex;
|
|
|
p->data.pos = LocationVacm;
|
|
|
m_vacm_lst[vacmIndex - 1] = p;
|
|
|
LOG_INF1("create product:%s", p->data.sn);
|
|
|
if (m_hash_lst.find(sn) == m_hash_lst.end())
|
|
|
{//没有则插入
|
|
|
m_hash_lst.insert(pair<string, CProduct*>(sn, p));
|
|
|
}
|
|
|
sys_LeaveCriticalSection(m_hSection);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::MovetoTest(int vacmIndex, int testIndex)
|
|
|
{//物料搬运
|
|
|
int ret = 0;
|
|
|
CProduct* p = NULL;
|
|
|
CTest* ptest = NULL;
|
|
|
|
|
|
RETURN_CHK_NOPRT(vacmIndex > 0 && vacmIndex <= m_vacm_cnt, ERR_INPUT_PARAM);
|
|
|
RETURN_CHK_NOPRT(testIndex > 0 && testIndex <= TESTCNT, ERR_INPUT_PARAM);
|
|
|
|
|
|
p = m_vacm_lst[vacmIndex - 1];
|
|
|
ptest = m_ptest[testIndex - 1];
|
|
|
|
|
|
RETURN_CHK_NOPRT(p, ERR_NO_PRODUCT);
|
|
|
RETURN_CHK_NOPRT(!ptest->_p, ERR_EXIST_PRODUCT);
|
|
|
RETURN_CHK_NOPRT(ptest->IsReady(), ERR_NOREADY);
|
|
|
|
|
|
ret = m_ptest[testIndex - 1]->StartTest(p, m_cfg.machine, m_cfg.Config, m_cfg.ConfigD,
|
|
|
m_cfg.sitel, m_cfg.project, m_cfg.bUpMes, m_cfg.bUpMTcp, 0,m_cfg.sublotname,m_cfg.bUpNoise);
|
|
|
|
|
|
RETURN_CHK_NOPRT(!ret, ret);
|
|
|
|
|
|
m_prePut = testIndex; //保存上一次放料
|
|
|
m_vacm_lst[vacmIndex - 1] = NULL; //清空吸嘴
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::MovetoVacm(int testIndex, int vacmIndex)
|
|
|
{//物料搬运
|
|
|
CProduct* p = NULL;
|
|
|
|
|
|
RETURN_CHK_NOPRT(vacmIndex > 0 && vacmIndex <= m_vacm_cnt, ERR_INPUT_PARAM);
|
|
|
RETURN_CHK_NOPRT(testIndex > 0 && testIndex <= TESTCNT, ERR_INPUT_PARAM);
|
|
|
RETURN_CHK_NOPRT(!m_vacm_lst[vacmIndex - 1], ERR_EXIST_PRODUCT);
|
|
|
RETURN_CHK_NOPRT(m_ptest[testIndex-1]->IsReady(), ERR_NOREADY);
|
|
|
|
|
|
p = m_ptest[testIndex-1]->_p;
|
|
|
|
|
|
RETURN_CHK_NOPRT(p, ERR_NO_PRODUCT);
|
|
|
|
|
|
p->data.index = vacmIndex;
|
|
|
p->data.pos = LocationVacm;
|
|
|
m_ptest[testIndex-1]->_p = NULL;
|
|
|
m_vacm_lst[vacmIndex-1] = p;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::MovetoStock(int vacmIndex, int sindex)
|
|
|
{//物料搬运-料仓
|
|
|
CProduct* p = NULL;
|
|
|
|
|
|
RETURN_CHK_NOPRT(vacmIndex > 0 && vacmIndex <= m_vacm_cnt, ERR_INPUT_PARAM);
|
|
|
RETURN_CHK_NOPRT(sindex >= LocationOk && sindex <= LocationNg3, ERR_INPUT_PARAM);
|
|
|
|
|
|
p = m_vacm_lst[vacmIndex-1];
|
|
|
|
|
|
RETURN_CHK_NOPRT(p, ERR_NO_PRODUCT);
|
|
|
|
|
|
MakeDate(p->data.end);
|
|
|
PutToStock(sindex, p);
|
|
|
m_vacm_lst[vacmIndex-1] = NULL;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::WaitTestIdle(int testIndex, int timeout)
|
|
|
{//等待测试治具就绪
|
|
|
uint ct = sys_GetTickCount();
|
|
|
|
|
|
RETURN_CHK_NOPRT(testIndex > 0 && testIndex <= TESTCNT, ERR_INPUT_PARAM);
|
|
|
RETURN_CHK_NOPRT(m_ptest[testIndex-1]->Enabled(), ERR_NOREADY);
|
|
|
|
|
|
while (1)
|
|
|
{
|
|
|
if (m_ptest[testIndex-1]->IsReady())
|
|
|
{//就绪
|
|
|
return 0;
|
|
|
}
|
|
|
if (sys_GetTickCount() > ct + timeout)
|
|
|
{//超时
|
|
|
return ERR_TIMEOUT;
|
|
|
}
|
|
|
sys_Sleep(5); //这里需要设置延时,否则占用CPU严重
|
|
|
}
|
|
|
return ERR_TIMEOUT;
|
|
|
}
|
|
|
|
|
|
int CManage::WaitM2Result(int sindex, char* szres, int timeout)
|
|
|
{//WaitM2 sindex sindex料仓编号[1-5] 等待2号相机处理结果,自动刷新产品标识到数组中,消息返回格式:res 0标识成功
|
|
|
TOpsCfg cfg;
|
|
|
int res = 0;
|
|
|
int bret = 0;
|
|
|
int index = 0;
|
|
|
int start = 0;
|
|
|
TMatrixInfo mat;
|
|
|
char* ptmp = NULL;
|
|
|
char* pnext = NULL;
|
|
|
char buff[1024] = {0};
|
|
|
|
|
|
RETURN_CHK_NOPRT(sindex >= LocationInput && sindex <= LocationNg3, ERR_INPUT_PARAM);
|
|
|
|
|
|
ops_get_cfg(&cfg);
|
|
|
if (cfg.offVision)
|
|
|
{//屏蔽视觉
|
|
|
sprintf(szres, "0");
|
|
|
StockReset(sindex);
|
|
|
set_matrix_cur_node(sindex, 0);
|
|
|
#if 0
|
|
|
if (LocationInput == sindex)
|
|
|
{//模拟一下进料仓数据
|
|
|
get_matrix_info(sindex, &mat);
|
|
|
if (IsFourpic()) mat.size *= 4;
|
|
|
for (int i = 0; i < mat.size; i++)
|
|
|
{
|
|
|
res = (i < 10 || (i < 26 && i >= 16)) ? 0 : 1;
|
|
|
if (res) MakeProduct(sindex, index);
|
|
|
else ReleaseProduct(sindex, index);
|
|
|
if (0 == start && LocationInput == sindex && res)
|
|
|
{//进料盘,等下设置料盘当前节点
|
|
|
start = index + 1;
|
|
|
}
|
|
|
else if (0 == start && LocationInput != sindex && !res)
|
|
|
{//出料盘
|
|
|
start = index + 1;
|
|
|
}
|
|
|
index++;
|
|
|
}
|
|
|
if (start > 0 && IsFourpic() && (LocationInput == sindex))
|
|
|
{//计算缩小后的料盘索引
|
|
|
int r = (start - 1) / (mat.col * 2) / 2; //new row
|
|
|
int c = (start - 1) % (mat.col * 2) / 2; //new col
|
|
|
start = r * mat.col + c + 1;
|
|
|
}
|
|
|
|
|
|
set_matrix_cur_node(sindex, start > 0 ? start - 1 : mat.size);
|
|
|
}
|
|
|
#else
|
|
|
if (LocationInput == sindex) MakeInput();
|
|
|
#endif
|
|
|
return 0; //返回成功
|
|
|
}
|
|
|
|
|
|
res = m_pVision[EVHamal]->WaitResult(buff, timeout);
|
|
|
|
|
|
RETURN_CHK_NOPRT(!res, res);
|
|
|
|
|
|
//处理结果
|
|
|
ptmp = sys_strtok(buff, ",", &pnext);
|
|
|
if (!ptmp || 0 == *ptmp) return 0;
|
|
|
res = atoi(ptmp);
|
|
|
if (0 != res)
|
|
|
{//拍照失败
|
|
|
sprintf(szres, "%d", res); //res==0才有后面的结果,否则直接返回接收结果成功
|
|
|
return 0; //指令返回成功
|
|
|
}
|
|
|
|
|
|
while(ptmp = sys_strtok(NULL, ",", &pnext))
|
|
|
{
|
|
|
if (EMSTR_INT != get_str_type(ptmp))
|
|
|
{//格式错误
|
|
|
REPORT("M2 reply format error");
|
|
|
return ERR_INPUT_PARAM;
|
|
|
}
|
|
|
res = atoi(ptmp); //标识有无物料
|
|
|
if (res)
|
|
|
{//有物料
|
|
|
MakeProduct(sindex, index);
|
|
|
if (LocationInput != sindex) bret = 1; //其它仓判定有物料
|
|
|
}
|
|
|
else
|
|
|
{//缺物料
|
|
|
ReleaseProduct(sindex, index);
|
|
|
if (LocationInput == sindex) bret = 1; //进料仓判定缺物料
|
|
|
}
|
|
|
if (0 == start && LocationInput == sindex && res)
|
|
|
{//进料盘,等下设置料盘当前节点
|
|
|
start = index + 1;
|
|
|
}
|
|
|
else if (0 == start && LocationInput != sindex && !res)
|
|
|
{//出料盘
|
|
|
start = index + 1;
|
|
|
}
|
|
|
index++;
|
|
|
}
|
|
|
|
|
|
get_matrix_info(sindex, &mat);
|
|
|
if (start > 0 && IsFourpic() && (LocationInput == sindex))
|
|
|
{//计算缩小后的料盘索引
|
|
|
int r = (start - 1) / (mat.col * 2) / 2; //new row
|
|
|
int c = (start - 1) % (mat.col * 2) / 2; //new col
|
|
|
start = r * mat.col + c + 1;
|
|
|
}
|
|
|
|
|
|
sprintf(szres, "%d", bret); //返回0正常,返回1标识缺产品或者有产品
|
|
|
set_matrix_cur_node(sindex, start > 0 ? start - 1 : mat.size); //设置为结束,表明要换盘
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int CManage::SetPosxy(int sindex, char* pszcmd)
|
|
|
{//pszcmd index sn offsetx offsety
|
|
|
int index = 0;
|
|
|
TMatrixInfo mat;
|
|
|
TMatrixNode node;
|
|
|
TPosxy* p = NULL;
|
|
|
char* sn = NULL;
|
|
|
char* ptmp = NULL;
|
|
|
|
|
|
RETURN_CHK_NOPRT(pszcmd && sindex >= LocationInput && sindex <= LocationNg3, ERR_INPUT_PARAM);
|
|
|
|
|
|
//index
|
|
|
trim_char(pszcmd);
|
|
|
ptmp = sys_strtok(NULL, " ", &pszcmd);
|
|
|
RETURN_CHK_NOPRT(EMSTR_INT == get_str_type(ptmp), ERR_INPUT_PARAM);
|
|
|
index = atoi(ptmp);
|
|
|
RETURN_CHK_NOPRT(index > 0 && index <= 4, ERR_INPUT_PARAM);
|
|
|
get_matrix_info(sindex, &mat);
|
|
|
get_matrix_cur_node(sindex, &node);
|
|
|
if (IsFourpic() && LocationInput == sindex)
|
|
|
{//4次拍照 index依次传入1234 对应位置位左上、右上、左下、右下
|
|
|
node.index = (node.col - 1) * 2 + (node.row - 1) * 2 * mat.col * 2
|
|
|
+ ((index - 1) / 2) * mat.col * 2 + (index - 1) % 2 + 1;
|
|
|
}
|
|
|
|
|
|
//sn
|
|
|
trim_char(pszcmd);
|
|
|
sn = sys_strtok(NULL, " ", &pszcmd);
|
|
|
RETURN_CHK_NOPRT(pszcmd && sn && *sn && strlen(sn) < MAX_NAME_LEN, ERR_INPUT_PARAM);
|
|
|
|
|
|
//x y
|
|
|
trim_char(pszcmd);
|
|
|
ptmp = sys_strtok(NULL, " ", &pszcmd);
|
|
|
if (pszcmd) trim_char(pszcmd);
|
|
|
RETURN_CHK_NOPRT(get_str_type(ptmp) && get_str_type(pszcmd), ERR_INPUT_PARAM);
|
|
|
|
|
|
p = new TPosxy;
|
|
|
p->x = atof(ptmp);
|
|
|
p->y = atof(pszcmd);
|
|
|
p->index = node.index;
|
|
|
comm_strcpy(p->sn, sn);
|
|
|
sys_EnterCriticalSection(m_hSection);
|
|
|
m_lst_pos[sindex - LocationInput].push_back(p);
|
|
|
sys_LeaveCriticalSection(m_hSection);
|
|
|
return 0;
|
|
|
}
|