#include "pch.h" #include "PLCSignalListener.h" // === ÈÕÖ¾´òÓ¡ÀàÐÍ === #define LOG_TYPE_ERROR -1 #define LOG_TYPE_SUCCESS 0 #define LOG_TYPE_WARNING 1 #define LOG_TYPE_NORMAL 2 // === PLC ¿ØÖÆÃüÁîÊäÈëλÅäÖà === #define PLC_CMD_BIT_START 0 // PLCÃüÁîÆðʼλ£¨Í¨³£ÎªB0£© #define PLC_CMD_BIT_COUNT 2 // ×ܹ²¼¸¸öÃüÁî루B0=Start, B1=Stop£© // === PLC ÐźżàÌýÆ÷Ïà¹Øºê¶¨Òå === #define PLC_ACK_MAX_LIFE 5 // PLCÏìÓ¦ÐźÅ×î´ó±£ÁôÖÜÆÚÊý£¨Ã¿ÖÜÆÚΪ m_nIntervalMs ºÁÃ룩 #define PLC_ACK_BASE_BIT 10 // PLCÓ¦´ðÆðʼµØÖ·£¨B10±íʾB0µÄÓ¦´ð£»B11±íʾB1£© // === PLCÈíÔª¼þÀàÐͺ꣨ÓÃÓÚÓ¦´ð¡¢Êý¾ÝдÈ룩=== #define PLC_BIT_DEVICE_TYPE DeviceType::B // λ²Ù×÷É豸ÀàÐÍ£¨ÈçM¡¢B£© #define PLC_WORD_DEVICE_TYPE DeviceType::W // ×Ö²Ù×÷É豸ÀàÐÍ£¨ÈçD¡¢W£© #define IS_RISING_EDGE(prev, curr) (!(prev) && (curr)) CPLCSignalListener::CPLCSignalListener() = default; CPLCSignalListener::~CPLCSignalListener() { Stop(); } bool CPLCSignalListener::Initialize(StationIdentifier station, int nIntervalMs/* = 200*/) { m_pPlc = std::make_unique(); if (!m_pPlc) { if (m_cbLog) { m_cbLog(_T("PLC¿ØÖÆÆ÷³õʼ»¯Ê§°Ü£¬ÎÞ·¨´´½¨ CCCLinkIEControl ʵÀý¡£"), LOG_TYPE_ERROR); } return false; } int ret = m_pPlc->Connect(CC_LINK_IE_CONTROL_CHANNEL(1)); if (ret != 0) { m_bConnected = false; if (m_cbLog) { CString strError; strError.Format(_T("PLC¿ØÖÆÆ÷Á¬½Óʧ°Ü£¬´íÎóÂ룺%d"), ret); m_cbLog(strError, LOG_TYPE_ERROR); } return false; } m_bConnected = true; m_station = station; m_nIntervalMs = nIntervalMs; m_vecPrevBits.assign(PLC_CMD_BIT_COUNT, false); return true; } void CPLCSignalListener::SetStartCallback(Callback cb) { m_cbStart = std::move(cb); } void CPLCSignalListener::SetStopCallback(Callback cb) { m_cbStop = std::move(cb); } void CPLCSignalListener::SetAnalyzeCallback(AnalyzeCallback cb) { m_cbAnalyze = std::move(cb); } void CPLCSignalListener::SetLogCallback(LogCallback cb) { m_cbLog = std::move(cb); } bool CPLCSignalListener::Start() { if (m_bRunning || !m_pPlc) { if (m_cbLog) { m_cbLog(_T("PLCÐźżàÌýÆ÷ÒÑÔÚÔËÐлòPLC¿ØÖÆÆ÷δ³õʼ»¯¡£"), LOG_TYPE_ERROR); } return false; } m_bRunning = true; m_thread = std::thread(&CPLCSignalListener::ThreadProc, this); return true; } void CPLCSignalListener::Stop() { m_bRunning = false; if (m_thread.joinable()) { m_thread.join(); } } void CPLCSignalListener::PulseBitDevice(DeviceType eDevType, short nBitNo, int nDelayMs/* = 50*/) { m_pPlc->SetBitDevice(m_station, eDevType, nBitNo); ::Sleep(nDelayMs); m_pPlc->ResetBitDevice(m_station, eDevType, nBitNo); } void CPLCSignalListener::HandleAckLife(int i, bool bCurrTriggerBit) { if (m_vecAckSent[i] && !bCurrTriggerBit) { m_pPlc->ResetBitDevice(m_station, PLC_BIT_DEVICE_TYPE, short(PLC_ACK_BASE_BIT + i)); m_vecAckSent[i] = false; } if (m_vecAckSent[i]) { if (++m_vecAckCounter[i] > PLC_ACK_MAX_LIFE) { m_pPlc->ResetBitDevice(m_station, PLC_BIT_DEVICE_TYPE, short(PLC_ACK_BASE_BIT + i)); m_vecAckSent[i] = false; } } } void CPLCSignalListener::ThreadProc() { while (m_bRunning) { BitContainer vecBits; int ret = m_pPlc->ReadBitData(m_station, PLC_BIT_DEVICE_TYPE, PLC_CMD_BIT_START, PLC_CMD_BIT_COUNT, vecBits); if (ret != 0/*&& vecBits.size() != PLC_CMD_BIT_COUNT*/) { ::Sleep(m_nIntervalMs); if (m_cbLog) { CString strError; strError.Format(_T("PLC¶ÁȡλÊý¾Ýʧ°Ü£¬´íÎóÂ룺%d"), ret); m_cbLog(strError, LOG_TYPE_ERROR); } continue; } for (int i = 0; i < PLC_CMD_BIT_COUNT; ++i) { if (IS_RISING_EDGE(m_vecPrevBits[i], vecBits[i])) { // ÉÏÉýÑØ´¥·¢ switch (i) { case 0: if (m_cbStart) { m_cbStart(); WriteOutValues(OutValuesArray{ 0.0, 0.0, 0.0, 0.0 }); if (m_pPlc->SetBitDevice(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) { m_vecAckSent[i] = true; m_vecAckCounter[i] = 0; } } break; case 1: if (m_cbStop) { m_cbStop(); if (m_pPlc->SetBitDevice(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) { m_vecAckSent[i] = true; m_vecAckCounter[i] = 0; } } if (m_cbAnalyze) { auto results = m_cbAnalyze(); WriteOutValues(results); } break; } } HandleAckLife(i, vecBits[i]); m_vecPrevBits[i] = vecBits[i]; } ::Sleep(m_nIntervalMs); } } bool CPLCSignalListener::WriteOutValues(const OutValuesArray& values) { if (!m_pPlc) { if (m_cbLog) { m_cbLog(_T("PLC¿ØÖÆÆ÷δ³õʼ»¯£¬ÎÞ·¨Ð´ÈëÊä³öÖµ¡£"), LOG_TYPE_ERROR); } return false; } static const short PLC_RESULT_ADDR[4] = { 100, 102, 104, 106 }; for (int i = 0; i < 4; ++i) { uint16_t nScaled = static_cast(std::round(values[i] * 100.0)); WordContainer vec = { nScaled }; int ret = m_pPlc->WriteWordData(m_station, PLC_WORD_DEVICE_TYPE, PLC_RESULT_ADDR[i], vec); if (ret != 0) { return false; } } return true; }