Ардуино и температурный контроллер Yudian AI518

Maximus
Offline
Зарегистрирован: 24.07.2015

Добрый день товарищи!

Пытаюсь достучаться до температурного контроллера Yudian AI518 и получать с него какие то данные.

Получается отправлять запрос, контроллер на запрос отвечает, но это происходит не стабильно. И почему то отправка-прием идет только при открытие в IDE монитоинга порта. Короче мои подозрения на таймер, по протоколу нужно отправлять-принимать с определенным интервалом. Я новичек, пожтому тут у меня возникли вопросы. Кому не сложно посмотрите пожуйста, буду очень благодарен за помощь, пишете в лс, в долгу не останусь. Очень нужно эту проблему решить.

Ниже ссылки на описание протокола:https://yadi.sk/i/ifrEqsR-3QzYD4

 

Код скейтча:

#include <MsTimer2.h>
#define DIR 8 // переключатель прием\передача
#define RDTYPE                                  (82)
#define WRTYPE                                  (134)
#define ERR_OK          (0)
#define ERR_ERROR       (1)
#define ERR_TIMEOUT       (2)
#define ERR_INVALIED_PARAM                      (3)
 
int totalSek = 0;
 
void to_Timer() {
  totalSek ++;//каждую мл.сек увеличиваем totalSek
}
static uint8_t u8ResBuff[] = {3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 3, 2, 2, 2};
static uint8_t u8InputStandard = 0;
 
 
struct tag_METERDATA_T
{
  float fAijPV;
  float fAijSV;
  float fAijMv;
  float fAijParam;
  uint8_t u8Alm;
};
 
 
struct tagREQ_FRM_T
{
  uint8_t  u8DevAddr1;
  uint8_t  u8DevAddr2;
  uint8_t  u8ReqType;
  uint8_t  u8DevPara;
  uint8_t  u8LoParam;
  uint8_t u8HiParam;
  uint8_t  u8LoSumCheck;
  uint8_t  u8HiSumCheck;
} ;
 
 
struct tagANS_FRM_T
{
  uint8_t  u8LoPV;
  uint8_t  u8HiPV;
  uint8_t  u8LoSV;
  uint8_t  u8HiSV;
  uint8_t  u8LoMV;
  uint8_t  u8HiMV;
  uint8_t  u8ALm;
  uint8_t  u8LoParam;
  uint8_t  u8HiParam;
  uint8_t  u8SumCheck;
};
 
 
int ReadParam(Stream &p_Serial, uint8_t u8DevAddr, uint16_t u16DevPara, struct tagANS_FRM_T &stAnsFrm)
{
  Serial.println("6");
  struct tagREQ_FRM_T stReqFrm;
  uint32_t n32CheckSum = 0;
  uint8_t u8Temp = 0;
  int nErrCnt = 0;
  int nError = ERR_ERROR;
  u8Temp = u16DevPara % 256;//подозрения
 
  stReqFrm.u8DevAddr1 = 0x80 + u8DevAddr;
  stReqFrm.u8DevAddr2 = 0x80 + u8DevAddr;
  stReqFrm.u8ReqType = RDTYPE;// + (u16DevPara >> 8);//подозрения
  stReqFrm.u8DevPara = 0;
  stReqFrm.u8LoParam = 0;
  stReqFrm.u8HiParam = 0;
  n32CheckSum = u8DevAddr + (stReqFrm.u8DevPara << 8) + stReqFrm.u8ReqType;
  stReqFrm.u8LoSumCheck = n32CheckSum & 0xff;
  stReqFrm.u8HiSumCheck = ( n32CheckSum >> 8) & 0xff;
 
  while (nErrCnt < 6)
  {
    Serial.println("7");
    if (SendFrame(p_Serial, (const byte *)&stReqFrm, sizeof(tagREQ_FRM_T), 200))
    {
      Serial.println("8");
      if (ReceiveFrame(p_Serial, (byte *)&stAnsFrm, sizeof(tagANS_FRM_T), 200))
      {
        Serial.println("9");
        if (GetSumCheck(stAnsFrm))
        {
          Serial.println("10");
          if (u16DevPara == 0x16)
          {
            Serial.println("11");
            u8InputStandard = stAnsFrm.u8LoParam;//????что это
          }
          nErrCnt = 10;
          nError = ERR_OK;
        }
      }
    }
    nErrCnt++;
  }
 
  return nError;
}
 
 
bool ReadParam(Stream &p_Serial, uint8_t u8DevAddr, uint16_t u16DevPara, float & fParaValue)//как я понимаю основная функция которой пользуемся
{
  struct tagANS_FRM_T stAnsFrm;
  if (ReadParam(p_Serial, u8DevAddr, u16DevPara, stAnsFrm) == ERR_OK)
  {
    int nTempVal = 0;
    nTempVal = Get2Byte(stAnsFrm.u8LoParam, stAnsFrm.u8HiParam);
    fParaValue = (float)GetSinglePara(nTempVal, u16DevPara);
 
    if (u16DevPara == 0x16)
    {
      u8InputStandard = stAnsFrm.u8LoParam;
    }
    return true;
  }
 
  return false;
}
 
uint16_t Get2Byte(uint8_t u8LoByte, uint8_t u8HiByte)
{
  uint16_t nsValue = 0;
 
  nsValue |= (u8HiByte << 8);
  nsValue &= 0xFF00;
  nsValue |= u8LoByte;
 
  return nsValue;
}
 
int GetSinglePara(uint32_t n32Value, uint16_t u16DevPara)
{
  int nRetPara = 0;
  int nTempVal = 0;
  int nFactor = 0;
 
  nFactor = GetFactor(u8ResBuff[u8InputStandard]);//вот тут
 
  switch (u16DevPara)
  {
    case 0:
      nRetPara = n32Value / 100;
      break;
 
    case 3:
    case 4:
    case 5:
    case 6:
    case 24:
    case 25:
    case 33:
    case 37:
    case 38:
    case 39:
      nTempVal = IntToFloat(n32Value, 0);
      nRetPara = nTempVal / nFactor;
      break;
 
    case 7:
    case 21:
    case 26:
      nRetPara = n32Value / nFactor;
      break;
 
    default:
      if (u16DevPara > 50)
      {
        if (u16DevPara % 2)
        {
          nTempVal = IntToFloat(n32Value, 0);
          nRetPara = nTempVal / nFactor;
        }
        else
        {
          nRetPara = nTempVal / 10;
        }
      }
      else
      {
        nRetPara = n32Value;
      }
 
      break;
  }
 
  return nRetPara;
}
 
int IntToFloat(uint32_t n32Value, uint8_t u8Value)
{
  int nRetVal = 0;
  int nTemp = 1;
 
  if (n32Value < 0)
  {
    nTemp = -1;
    n32Value = -n32Value;
  }
 
  if (n32Value < 10000)
  {
    nRetVal = n32Value;
  }
  else if (n32Value < 19000)
  {
    nRetVal = (n32Value - 9000) * 10 + u8Value;
  }
  else if (n32Value < 28000)
  {
    nRetVal = ((n32Value - 18000) * 10 + u8Value) * 10;
  }
  else
  {
    nRetVal = ((n32Value - 27000) * 10 + u8Value) * 100 ;
  }
 
  return nRetVal * nTemp;
}
 
 
bool GetSumCheck(struct tagANS_FRM_T stAnsFrm)
{
  uint8_t  u8CrcVal = 0;
  uint8_t u8CalCrcVal = 0;
  uint8_t u8TempCheck;
  bool bResult = false;
  Serial.println("20");
  u8TempCheck = stAnsFrm.u8SumCheck % 16;
  u8CrcVal = ((stAnsFrm.u8HiPV + stAnsFrm.u8LoPV + stAnsFrm.u8HiSV + stAnsFrm.u8LoSV +
               stAnsFrm.u8LoMV + stAnsFrm.u8HiMV + stAnsFrm.u8HiParam + stAnsFrm.u8LoParam +
               stAnsFrm.u8ALm + u8TempCheck) % 256) / 16;
               
 
  u8CalCrcVal = stAnsFrm.u8SumCheck / 16;
 
  if (u8CrcVal == u8CalCrcVal)
  {
    Serial.println("21");
    bResult = true;
  }
  Serial.println("22");
  return bResult;
}
 
int WriteParam(Stream &p_Serial, uint8_t u8DevAddr, uint16_t u16DevPara, uint8_t u8LoParam, uint8_t u8HiParam, struct tagANS_FRM_T &stAnsFrm)
{
  struct tagREQ_FRM_T stReqFrm;
  uint32_t n32CheckSum = 0;
  uint8_t u8Temp = 0;
  int nErrCnt = 0;
  int nError = ERR_ERROR;
  u8Temp = u16DevPara % 256;
 
  stReqFrm.u8DevAddr1 = 0x80 + u8DevAddr;
  stReqFrm.u8DevAddr2 = 0x80 + u8DevAddr;
  stReqFrm.u8ReqType = WRTYPE + (u16DevPara >> 8);
  stReqFrm.u8DevPara = u8Temp;
  stReqFrm.u8LoParam = u8LoParam;
  stReqFrm.u8HiParam = u8HiParam;
  n32CheckSum = u8DevAddr + (stReqFrm.u8DevPara << 8) + stReqFrm.u8ReqType;
  stReqFrm.u8LoSumCheck = n32CheckSum & 0xff;
  stReqFrm.u8HiSumCheck = ( n32CheckSum >> 8) & 0xff;
 
  while (nErrCnt < 6)
  {
    if (SendFrame(p_Serial, (const byte *)&stReqFrm, sizeof(struct tagREQ_FRM_T), 200))
    {
      if (ReceiveFrame(p_Serial, (byte *)&stAnsFrm, sizeof(struct tagANS_FRM_T), 200))
      {
        if (GetSumCheck(stAnsFrm))
        {
          if (u16DevPara == 0x16)
          {
            u8InputStandard = stAnsFrm.u8LoParam;
          }
 
          nErrCnt = 10;
          nError = ERR_OK;
        }
      }
    }
    nErrCnt++;
  }
 
  return nError;
}
 
bool SendFrame(Stream &p_Serial, const byte *pcFrameBuff, uint64_t nFrameSize, int nTimeOut)
{
  /*QTime time;
      time.start();
 
      while((time.elapsed() < nTimeOut) && (nFrameSize > 0))
      {
          qint64 nWriteBytes = WriteData(pcFrameBuff, nFrameSize);
          pcFrameBuff += nWriteBytes;
          nFrameSize -= nWriteBytes;
      }
 
      return (nFrameSize==0);*/
 
 
  MsTimer2::set(1, to_Timer); // Здесь задаем период 1 м.секунда
  totalSek = 0;
  MsTimer2::start();//Стартуем, теперь таймер запущен
  Serial.println("12");
  while ((totalSek < nTimeOut) && (nFrameSize > 0))
  {
    uint64_t nWriteBytes = WriteData(p_Serial, pcFrameBuff, nFrameSize);
    pcFrameBuff += nWriteBytes;
    nFrameSize -= nWriteBytes;
    //   Serial.println((int)nWriteBytes);
    //Serial.println((int)pcFrameBuff);
    //Serial.println((int)nFrameSize);
 
  }
  MsTimer2::stop();
  totalSek = 0;
  Serial.println("222");
  return (nFrameSize == 0);
}
 
 
bool ReceiveFrame(Stream &p_Serial, byte *pcFrameBuff, uint64_t nFrameSize, int nTimeOut)
{
 
  /* QTime Time;
     Time.start();
     qint64 nReadCurCount = 0;
 
     while((Time.elapsed()< nTimeOut) && (nReadCurCount < nFrameSize))
     {
         qint64 nReadBytes = ReadData(pcFrameBuff, nFrameSize);
         pcFrameBuff += nReadBytes;
         nReadCurCount += nReadBytes;
     }
 
     return(nReadCurCount == nFrameSize);
  */
 
  uint64_t nReadCurCount = 0;
  Serial.println("14");
  MsTimer2::set(1, to_Timer); // Здесь задаем период 1 м.секунда
  totalSek = 0;
  MsTimer2::start();//Стартуем, теперь таймер запущен
 
  while ((totalSek  < nTimeOut) && (nReadCurCount < nFrameSize))
  {
    uint64_t nReadBytes = ReadData(p_Serial, pcFrameBuff, nFrameSize);
    pcFrameBuff += nReadBytes;
    nReadCurCount += nReadBytes;
  }
  MsTimer2::stop();
  totalSek = 0;
  Serial.println("16");
  return (nReadCurCount == nFrameSize);
}
 
uint64_t WriteData(Stream &p_Serial, const byte *pcWriteBuff, uint64_t nWriteLenth)//нужно переписать
{
  digitalWrite(DIR, HIGH); // включаем передачу
  /*qint64 nTempWriteLenth=0;
    if((m_MyComPort != NULL) && (m_MyComPort->isOpen()))
    {
    nTempWriteLenth = m_MyComPort->write(pcWriteBuff, nWriteLenth);
    }
 
    return nTempWriteLenth;//Функция на Qt*/
 
 
  uint64_t nTempWriteLenth = nWriteLenth;
  //if ((m_MyComPort != NULL) && (m_MyComPort->isOpen())) //вот здесь полюбому переписать isOpen
  //{
  Serial.println(11111111);
  p_Serial.write(pcWriteBuff, nWriteLenth);
  // }
  
  delay(50);
 
  return nTempWriteLenth;
}
 
 
uint64_t ReadData(Stream &p_Serial, byte *pcReadBuff, uint64_t nReadLenth)//вот эту нужно переписать
{
  digitalWrite(DIR, LOW);//включить прием
  uint64_t nTempReadLenth = 0;
  Serial.println("88");
  /*if ((m_MyComPort != NULL) && (m_MyComPort->isOpen())) //вот здесь полюбому переписать isOpen
    {
    nTempReadLenth = m_MyComPort->read(pcReadBuff, nReadLenth);//вот с этим не понятно что делать
    }*/
  delay(50);
  if (p_Serial.available() > 0) {
    Serial.println("66");
    for (nTempReadLenth = 0; nTempReadLenth < nReadLenth; nTempReadLenth++) {
      Serial.println("55");
      pcReadBuff[nTempReadLenth] = p_Serial.read();
    }
  }
  return nTempReadLenth;
}
 
int WriteParam(Stream &p_Serial, uint8_t u8DevAddr, uint16_t u16DevPara, uint8_t u8LoParam, uint8_t u8HiParam)
{
  int nError = ERR_OK;
 
  struct tagANS_FRM_T stAnsFrm;
 
  nError = WriteParam(p_Serial, u8DevAddr, u16DevPara, u8LoParam, u8HiParam, stAnsFrm);
 
  return nError;
}
 
bool WriteParam(Stream &p_Serial, uint8_t u8DevAddr, uint16_t u16DevPara, float fParaValue)//как я понимаю основная функция которой пользуемся
{
  struct tagANS_FRM_T stAnsFrm;
  int nParaValue = 0;
 
  nParaValue = GetInputValue(u16DevPara, fParaValue);
 
 
  if (WriteParam(p_Serial,
                 u8DevAddr, u16DevPara,
                 (nParaValue & 0xFF), ((nParaValue >> 8) & 0xFF),
                 stAnsFrm) == ERR_OK)
  {
    if (u16DevPara == 0x16)
    {
      u8InputStandard = stAnsFrm.u8LoParam;
    }
    return true;
  }
 
  return false;
}
 
int GetInputValue(uint16_t u16DevPara, float fParaValue)
{
  int nRetPara = 1;
  int nTempValue = 0;
 
  switch (u16DevPara)
  {
    case 0:
      nRetPara = fParaValue * 100;
      break;
 
    case 3:
    case 4:
    case 5:
    case 6:
    case 24:
    case 25:
    case 33:
    case 37:
    case 38:
    case 39:
      nTempValue = fParaValue * GetFactor(u8ResBuff[u8InputStandard]);
      nRetPara = FloatToInt(nTempValue);
      break;
 
    case 7:
    case 21:
    case 26:
      nRetPara = fParaValue * GetFactor(u8ResBuff[u8InputStandard]);
      break;
 
    default:
      if (u16DevPara > 50)
      {
        if (u16DevPara % 2)
        {
          nTempValue = fParaValue * GetFactor(u8ResBuff[u8InputStandard]);
          nRetPara = FloatToInt(nTempValue);
        }
        else
        {
          nRetPara = fParaValue * GetFactor(u8ResBuff[u8InputStandard]);
        }
 
      }
      else
      {
        nRetPara = (int)fParaValue;
      }
 
      break;
  }
 
  return nRetPara;
}
 
int GetFactor(uint8_t u8Dpts)
{
  int nRetFactor = 1;
 
  if (u8Dpts == 2) nRetFactor = 100;
  if (u8Dpts == 3) nRetFactor = 1000;
 
  return nRetFactor;
}
 
 
int FloatToInt(uint32_t nParaValue)
{
  int nRetVal = 0;
  int nTemp = 1;
 
  if (nParaValue < 0)
  {
    nTemp = -1;
    nParaValue = -nParaValue;
  }
 
  if (nParaValue < 10000)
  {
    nRetVal =  nParaValue;
  }
  else if (nParaValue < 100000)
  {
    nRetVal = (nParaValue / 10) + 9000;
  }
  else if (nParaValue < 1000000)
  {
    nRetVal = (nParaValue / 100) + 18000;
  }
  else
  {
    nRetVal = (nParaValue / 1000) + 27000;
  }
 
  return nRetVal * nTemp;
}
 
float GetPvSv(uint32_t n32Value)
{
  float fTemPvSv = 0.0;
  fTemPvSv =  (float)n32Value / GetFactor(u8ResBuff[u8InputStandard]);
  return fTemPvSv;
 
}
 
/*Остались одна функция которыя ни где не учавствуют, это настройки порта, мы их зададим в setup:
   bool QComProtocol::myComPortOpen(QSerialParameter &myComPortPara)
  {
    //先判ж–*дёІеЏЈжЇеђ¦е*在,如果е*ењЁе€™е€*除重新创建
    if(m_MyComPort != NULL)
    {
        delete m_MyComPort;
        m_MyComPort = NULL;
    }
 
    m_MyComPort = new Win_QextSerialPort(myComPortPara.m_UartId,QextSerialBase::Polling);
    if( m_MyComPort->open(QIODevice::ReadWrite))
    {
        m_MyComPort->setBaudRate((BaudRateType)myComPortPara.m_UartBaud.toInt());
        m_MyComPort->setDataBits((DataBitsType)myComPortPara.m_UartDataBit.toInt());
        m_MyComPort->setStopBits((StopBitsType)myComPortPara.m_UartStopBit.toInt());
        m_MyComPort->setParity((ParityType)myComPortPara.m_UartParity.toInt());
        m_MyComPort->setFlowControl(FLOW_OFF);
        myComPortPara.isOpen = true;
        return true;
    }
    return false;
 
  }
*/
 
 
void setup() {// дальше я пока не трогал
  Serial.begin(9600);
  Serial2.begin(9600, SERIAL_8N2);
  pinMode(DIR, OUTPUT);
}
 
void loop() {
  tag_METERDATA_T g_stMeterData;
  tagANS_FRM_T stAnsFrm;
  uint16_t u16ParamAddr = 0;
  int nTempVal = 0;
  int nTempPv = 0;
  int nTempSv = 0;
  uint8_t u8Alm = 0;
  if (ReadParam(Serial2, 1, u16ParamAddr, stAnsFrm) == ERR_OK)
  {
#if 1
    Serial.println("2");
    nTempVal = Get2Byte(stAnsFrm.u8LoPV, stAnsFrm.u8HiPV);
    nTempPv = IntToFloat(nTempVal, 0);
    u8Alm = stAnsFrm.u8SumCheck % 16;
    nTempVal = Get2Byte(stAnsFrm.u8LoSV, stAnsFrm.u8HiSV);
 
    nTempSv = IntToFloat(nTempVal, u8Alm);
    nTempPv = nTempSv - nTempPv;
 
    g_stMeterData.fAijPV = GetPvSv(nTempPv);
    g_stMeterData.fAijSV = GetPvSv(nTempSv);
    g_stMeterData.fAijMv = (float)Get2Byte(stAnsFrm.u8LoMV, stAnsFrm.u8HiMV);
    g_stMeterData.u8Alm = stAnsFrm.u8ALm;
#endif
    Serial.println("3");
    nTempVal = Get2Byte(stAnsFrm.u8LoParam, stAnsFrm.u8HiParam);
    g_stMeterData.fAijParam = (float)GetSinglePara(nTempVal, u16ParamAddr);
 
    u16ParamAddr++;
 
    if (u16ParamAddr > 400)
    {
      Serial.println("4");
      u16ParamAddr = 0;
    }
 
  }
  Serial.println("5");
  Serial.println(nTempSv);
  delay (1000);
}

Выкладываю лог из порта, я в Serial выводил просто цифры отвечающие за этап выполнения программы.

 

55 это прием байта данных.

88 стоит перед проверкой , есть ли данные. Проверку не проходит, поэтому один восьмерки. Но вначале то все ок. Данные приходят, проерка контрольной суммы не проходит только, но это позже, сейчас надо добиться стабильного приема.

 

 

Maximus
Offline
Зарегистрирован: 24.07.2015

моя почта  : leonoffmaxim@gmail.com