using System; using System.Threading; using System.IO.Ports; using System.Windows.Forms; using LFP_Manager.DataStructure; using LFP_Manager.Function; namespace LFP_Manager.Threads { class csUartTheadEltek { #region VARIABLES private CommConfig Config; private DeviceSystemTotalData SystemTotalData; private DeviceSystemData[] SystemData; private Thread serialComm = null; private SerialPort sPort = null; private string Msg = ""; private bool SerialPortThreadEnd = true; private int SystemId = 0; private bool UartPolling = false; private bool AutoUartTx = true; private int addr_ch = 0; private ushort RequestRegAddr = 0x0000; //Byul Init 0x0000 private ushort RequestRegLen = 50; private bool rFlag = false; private int wFlag = 0; private ushort WriteRegAddr = 0x0000; //Byul Init 0x0000 private short WriteRegData = 0; public event UartDataUpdate OnUpdate = null; public event UartDataRecv OnDataRecv = null; public event UartDataPrint OnPrint = null; #endregion #region CONSTRUCTORS public csUartTheadEltek(int sId, CommConfig aConfig, ref DeviceSystemTotalData aSystemTotalData, ref DeviceSystemData[] aSystemData) { SystemId = sId; Config = aConfig; SystemTotalData = aSystemTotalData; SystemData = aSystemData; serialComm = new Thread(uartCommThread); } public void disposeThread() { if (sPort != null) { if (sPort.IsOpen) { sPort.Close(); } sPort = null; } SerialPortThreadEnd = true; if (serialComm != null) { if (serialComm.IsAlive) { serialComm.Abort(); } serialComm = null; } } public bool Start(CommConfig aConfig, int sId, bool aPolling) { bool result = false; SystemId = sId; UartPolling = aPolling; if (Open(aConfig.UartPort, 9600)) //Byul Init 9600 { SerialPortThreadEnd = false; serialComm.Start(); result = true; } return result; } public void Stop() { SerialPortThreadEnd = true; Close(); } #endregion public string GetMsg() { string result = Msg; Msg = ""; return result; } #region COMMPORT CONTROLS private void sDataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { byte[] sRead = new byte[1024]; int rLen = 0; try { rLen = ((SerialPort)sender).Read(sRead, 0, 1024); for (int i = 0; i < rLen; i++) { PutBuff(sRead[i]); } } catch (Exception) { } } private void sErrorReceived(object sender, System.IO.Ports.SerialErrorReceivedEventArgs e) { // //csMakeDataFunction.SetData() } private void sPinChanged(object sender, System.IO.Ports.SerialPinChangedEventArgs e) { // } private bool Open(string cPort, int cBaudrate) { sPort = new SerialPort(); sPort.PortName = cPort; sPort.BaudRate = cBaudrate; sPort.DataReceived += sDataReceived; sPort.ErrorReceived += sErrorReceived; sPort.PinChanged += sPinChanged; try { sPort.Open(); } catch (Exception ex) { throw new Exception("Error Open - " + ex.Message); } return sPort.IsOpen; } private void Close() { if (sPort != null) { if (sPort.IsOpen) { sPort.Close(); } sPort = null; } } #endregion #region PUBLIC FUNCTION public void SetPolling(bool flag, int sId, ref DeviceSystemData[] aSystemData) { SystemId = sId; UartPolling = flag; SystemData = aSystemData; SystemData[0].mNo = SystemId; } public void SetAutoTx(bool autoTx) { AutoUartTx = autoTx; } public void SetWriteCoilReg(ushort WriteAddr, short WriteData) { wFlag = 2; WriteRegAddr = WriteAddr; WriteRegData = WriteData; for (int i = 0; i < 500; i += 10) { Thread.Sleep(10); Application.DoEvents(); } } public void SetParam(ushort WriteAddr, short WriteData) { wFlag = 1; WriteRegAddr = WriteAddr; WriteRegData = WriteData; for (int i = 0; i < 500; i += 10) { Thread.Sleep(10); Application.DoEvents(); } } public void SendProcessFromApp(int sId, int mode, int index, int flag, ref DeviceParamData aParam, ref DeviceCalibration aCalib) { switch (mode) { case csConstData.UART_PARAM_LIST.CELL_UNDER_VOLTAGE: // Cell Under Volatge Parameter SetParam((ushort)(mode + 0), aParam.CellUnderVoltageWarning); SetParam((ushort)(mode + 1), aParam.CellUnderVoltageTrip); SetParam((ushort)(mode + 2), aParam.CellUnderVoltageRelease); break; case csConstData.UART_PARAM_LIST.CELL_OVER_VOLTAGE: // Cell Over Volatge Parameter SetParam((ushort)(mode + 0), aParam.CellOverVoltageWarning); SetParam((ushort)(mode + 1), aParam.CellOverVoltageTrip); SetParam((ushort)(mode + 2), aParam.CellOverVoltageRelease); break; case csConstData.UART_PARAM_LIST.PACK_UNDER_VOLTAGE: // Pack Under Volatge Parameter SetParam((ushort)(mode + 0), (short)(aParam.SysUnderVoltageWarning * 10)); SetParam((ushort)(mode + 1), (short)(aParam.SysUnderVoltageTrip * 10)); SetParam((ushort)(mode + 2), (short)(aParam.SysUnderVoltageRelease * 10)); break; case csConstData.UART_PARAM_LIST.PACK_OVER_VOLTAGE: // Pack Over Volatge Parameter SetParam((ushort)(mode + 0), (short)(aParam.SysOverVoltageWarning * 10)); SetParam((ushort)(mode + 1), (short)(aParam.SysOverVoltageTrip * 10)); SetParam((ushort)(mode + 2), (short)(aParam.SysOverVoltageRelease * 10)); break; case csConstData.UART_PARAM_LIST.CHG_LOW_TEMPERATURE: // Charge Low Temperature Parameter SetParam((ushort)(mode + 0), (short)(aParam.ChaLowTempWarning + 50)); //(short)(reg_value - 50) SetParam((ushort)(mode + 1), (short)(aParam.ChaLowTempTrip + 50)); SetParam((ushort)(mode + 2), (short)(aParam.ChaLowTempRelease + 50)); break; case csConstData.UART_PARAM_LIST.CHG_HIGH_TEMPERATURE: // Pack High Temperature Parameter SetParam((ushort)(mode + 0), (short)(aParam.ChaHighTempWarning + 50)); //(short)(reg_value - 50) SetParam((ushort)(mode + 1), (short)(aParam.ChaHighTempTrip + 50)); SetParam((ushort)(mode + 2), (short)(aParam.ChaHighTempRelease + 50)); break; case csConstData.UART_PARAM_LIST.DCH_LOW_TEMPERATURE: // Charge Low Temperature Parameter SetParam((ushort)(mode + 0), (short)(aParam.DchLowTempWarning + 50)); //(short)(reg_value - 50) SetParam((ushort)(mode + 1), (short)(aParam.DchLowTempTrip + 50)); SetParam((ushort)(mode + 2), (short)(aParam.DchLowTempRelease + 50)); break; case csConstData.UART_PARAM_LIST.DCH_HIGH_TEMPERATURE: // Pack High Temperature Parameter SetParam((ushort)(mode + 0), (short)(aParam.DchHighTempWarning + 50)); //(short)(reg_value - 50) SetParam((ushort)(mode + 1), (short)(aParam.DchHighTempTrip + 50)); SetParam((ushort)(mode + 2), (short)(aParam.DchHighTempRelease + 50)); break; case csConstData.UART_PARAM_LIST.CHG_OVER_CURRENT: // Charge Over Current Parameter //SetParam((ushort)(mode + 2), (short)(aParam.ChaOverCurrentRelease / 1)); //(short)(reg_value - 50) SetParam((ushort)(mode + 4), (short)(aParam.ChaOverCurrentTrip * 10)); SetParam((ushort)(mode + 7), (short)(aParam.ChaOverCurrentTrip2 * 10)); break; case csConstData.UART_PARAM_LIST.DCH_OVER_CURRENT: // Discharge Over Current Parameter //SetParam((ushort)(mode + 2), (short)(aParam.ChaOverCurrentRelease / 1)); //(short)(reg_value - 50) SetParam((ushort)(mode + 4), (short)(aParam.DchOverCurrentTrip * 10)); SetParam((ushort)(mode + 7), (short)(aParam.DchOverCurrentTrip2 * 10)); break; case csConstData.UART_PARAM_LIST.DEFAULT_PARAM: // Default Parameter int i = 0; Forms.fmxWait WaitForm = new Forms.fmxWait(); WaitForm.StartPosition = FormStartPosition.CenterScreen; try { WaitForm.Show(); i = csConstData.UART_PARAM_LIST.CELL_UNDER_VOLTAGE; SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Warn_Cell_UV)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Cell_UV)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Release_Cell_UV)); i = csConstData.UART_PARAM_LIST.PACK_UNDER_VOLTAGE; SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Warn_Pack_UV)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Pack_UV)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Release_Pack_UV)); i = csConstData.UART_PARAM_LIST.CELL_OVER_VOLTAGE; SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Warn_Cell_OV)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Cell_OV)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Release_Cell_OV)); i = csConstData.UART_PARAM_LIST.PACK_OVER_VOLTAGE; SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Warn_Pack_OV)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Pack_OV)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Release_Pack_OV)); i = csConstData.UART_PARAM_LIST.CHG_OVER_CURRENT; SetParam((ushort)(i + 4), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Charge_OC1)); SetParam((ushort)(i + 7), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Charge_OC2)); i = csConstData.UART_PARAM_LIST.DCH_OVER_CURRENT; SetParam((ushort)(i + 4), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Discharge_OC1)); SetParam((ushort)(i + 7), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Discharge_OC2)); i = csConstData.UART_PARAM_LIST.CHG_LOW_TEMPERATURE; SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Warn_Charge_UT)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Charge_UT)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Release_Charge_UT)); i = csConstData.UART_PARAM_LIST.CHG_HIGH_TEMPERATURE; SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Warn_Charge_OT + 50)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Charge_OT + 50)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Release_Charge_OT + 50)); i = csConstData.UART_PARAM_LIST.DCH_LOW_TEMPERATURE; SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Warn_Discharge_UT + 50)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Discharge_UT + 50)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Release_Discharge_UT + 50)); i = csConstData.UART_PARAM_LIST.DCH_HIGH_TEMPERATURE; SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Warn_Discharge_OT + 50)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Protect_Discharge_OT + 50)); SetParam((ushort)(i++), (short)(csConstData.UART_PARAM_DEFAULT.Release_Discharge_OT + 50)); } catch (Exception) { } finally { if (WaitForm != null) WaitForm.Close(); } break; case 0x000F: // Limit Charge SetWriteCoilReg(csConstData.UART_CALIB_ADDR_LIST.LIMIT_CHARGE, aCalib.Current.ChargeOption); break; default: break; } } #endregion #region RX BUFFERING const int BUFFER_SIZE = 512; byte[] rBuffer = new byte[BUFFER_SIZE]; int rBufStart = 0; int rBufEnd = 0; private void PutBuff(byte c) { rBuffer[rBufStart++] = c; rBufStart %= BUFFER_SIZE; if (rBufStart == rBufEnd) { rBufEnd++; rBufEnd %= BUFFER_SIZE; } } private int GetBuff() { int result = 0; if (rBufStart != rBufEnd) { result = 0x0100 + rBuffer[rBufEnd++]; rBufEnd %= BUFFER_SIZE; } return result; } private void FlushBuff() { rBufStart = rBufEnd = 0; } #endregion #region TX BUFFERING private byte[] MakeWriteRegData(ushort DevID, ushort WriteAddr, ushort WriteLen, ref ushort[] WriteData) { byte[] wData = null; if (WriteLen > 0) { } return wData; } private string MakeCheckSum(byte[] sData, int len) { string result = ""; int checksum = 0; for (int i = 0; i < len; i++) { checksum += sData[i + 1]; } checksum = ~checksum + 1; result = String.Format("{0:X2}{1:X2}", (byte)(checksum >> 8), (byte)checksum); return result; } private byte[] MakeTxDataVision(bool wData) { byte[] sData; if (wFlag == 1) { sData = csSerialCommFunction.MakeWriteRegisterData((ushort)SystemId, WriteRegAddr, WriteRegData); if (wFlag != 0) wFlag = 0; } else if (wFlag == 2) { sData = csSerialCommFunction.MakeWriteCoilData((ushort)SystemId, WriteRegAddr, WriteRegData); if (wFlag != 0) wFlag = 0; } else { ushort sCmd; switch (addr_ch) { case 0: addr_ch = 1; RequestRegAddr = csConstData.Eltek_Data.GetParamDataRegAddr(SystemId - 1); RequestRegLen = csConstData.Eltek_Data.ParaDataRegSize; sCmd = csSerialCommFunction.READ_HOLDING_REG; rFlag = true; break; case 1: addr_ch = 0; RequestRegAddr = csConstData.Eltek_Data.GetOpDataRegAddr(SystemId - 1); RequestRegLen = csConstData.Eltek_Data.OpDataRegSize; sCmd = csSerialCommFunction.READ_HOLDING_REG; rFlag = true; break; default: addr_ch = 0; RequestRegAddr = csConstData.Eltek_Data.GetOpDataRegAddr(SystemId - 1); RequestRegLen = csConstData.Eltek_Data.OpDataRegSize; sCmd = csSerialCommFunction.READ_HOLDING_REG; break; } sData = csSerialCommFunction.MakeReadRegisterData((ushort)SystemId, sCmd, RequestRegAddr, RequestRegLen); } return sData; } #endregion #region COMM THREAD byte[] ReadBuf = new byte[BUFFER_SIZE]; ushort rPosition = 0; bool BuffStart = false; private void RecvPacketInit() { BuffStart = false; rPosition = 0; } private void uartCommThread() { int getData = 0; byte cData = 0; int TimeOutCount = 0; StartSend: while (SerialPortThreadEnd == false) { if ((sPort == null) || (sPort.IsOpen == false)) continue; if (UartPolling && AutoUartTx) { FlushBuff(); byte[] txData = MakeTxDataVision(false); if (sPort == null) return; sPort.Write(txData, 0, txData.Length); if (rFlag == true) { int rTimeOut = 100; RecvPacketInit(); while (rTimeOut > 0) { if (((getData = GetBuff()) & 0x0100) != 0x0000) { rTimeOut = 100; TimeOutCount = 0; cData = (byte)(getData & 0x00FF); if (rPosition >= BUFFER_SIZE) RecvPacketInit(); if (BuffStart == false) { if (cData == (byte)SystemId) { rPosition = 0; ReadBuf[rPosition++] = cData; BuffStart = true; } } else { ReadBuf[rPosition++] = cData; switch (csSerialCommFunction.ModbusPacketFromSlaveCheck(ReadBuf, rPosition)) { case 0: // Need more data break; case 1: // Packet OK, no error SystemData[0].CommFail = false; SystemData[0].ShelfCommFail = false; short[] result_code = csSerialCommFunction.SerialRxProcess(ReadBuf, RequestRegAddr, rPosition, ref SystemData[0]); OnUpdate?.Invoke(this, ref SystemData); if (result_code[0] != 0) { if (OnDataRecv != null) { byte[] adata = new byte[8]; for (int j = 0; j < 2; j++) adata[j] = 0; adata[0] = (byte)(result_code[1] >> 8); adata[1] = (byte)(result_code[1] >> 0); OnDataRecv((UInt32)result_code[0], adata); } } Thread.Sleep(100); goto StartSend; case -1: // Packet error RecvPacketInit(); Thread.Sleep(100); goto StartSend; default: break; } } } else { Thread.Sleep(1); if (rTimeOut > 0) { rTimeOut--; } } } if (rPosition > 0) { Thread.Sleep(100); } else { TimeOutCount++; if (TimeOutCount >= 5) { TimeOutCount = 5; //SystemData[0].CommFail = true; if (SystemData[0].ShelfCommFail == false) { SystemData[0].ShelfCommFail = true; DataInit(); } } Thread.Sleep(100); } OnUpdate?.Invoke(this, ref SystemData); Thread.Sleep(1); } else { Thread.Sleep(100); } /* if (rFlag == true) */ rPosition = 0; } else { Thread.Sleep(500); } } } #endregion #region DATA INIT private void DataInit() { SystemData[0].ShelfCommFail = true; SystemData[0].cellQty = 15; SystemData[0].tempQty = 4; for (int j = 0; j < csConstData.SystemInfo.MAX_MODULE_CELL_SIZE; j++) { SystemData[0].ValueData.CellVoltage[j] = 0; } for (int j = 0; j < csConstData.SystemInfo.MAX_MODULE_TEMP_SIZE; j++) { SystemData[0].ValueData.CellTemperature[j] = 0; } SystemData[0].ValueData.voltageOfPack = 0; SystemData[0].ValueData.current = 0; SystemData[0].ValueData.rSOC = 0; SystemData[0].AvgData.maxCellVoltage = 0; SystemData[0].AvgData.minCellVoltage = 0; SystemData[0].AvgData.avgCellVoltage = 0; SystemData[0].AvgData.maxTemp = 0; SystemData[0].AvgData.minTemp = 0; SystemData[0].AvgData.avgTemp = 0; SystemData[0].heatbeat = 0; SystemData[0].StatusData.warning = 0; SystemData[0].StatusData.protection = 0; SystemData[0].StatusData.errorCode = 0; for (int j = 0; j < SystemData[0].Information.BMS_SN.Length; j++) { SystemData[0].Information.BMS_SN[j] = 0; } for (int j = 0; j < SystemData[0].Information.Module_SN.Length; j++) { SystemData[0].Information.Module_SN[j] = 0; } SystemData[0].CalibriationData.Battery.Capacity = 0; SystemData[0].CalibriationData.Current.ChaAndDchSelect = 0; SystemData[0].CalibriationData.Current.ChgCalibration_K = 0; SystemData[0].CalibriationData.Current.DchCalibration_K = 0; } #endregion } }