#include "IO.h" #include "VarClass.h" #include "HmiClass.h" #include "UtilClass.h" #include "motor.h" #include "arduino.h" unsigned long errtime = 0; unsigned long eruntime = 0; void HmiClass::Setup() { hmi.SendMessage("##:HMI:SETUP", false); updatetime = millis(); ClearTempBuffer0(); ClearTempBuffer1(); } void HmiClass::Update() { //데이터는 일정 주기로 전송한다. unsigned long runtime = millis() - updatetime; uint8_t loopterm = var._eep_iosendinterval; loopterm = 500; //설정 중에는 통신속도를 초당 10번으로 고정한다 if (var.getFlag(FLAG_SETUP) == true) loopterm = 100; if (runtime > loopterm) { //IO상태전송 SendIOStatus(); //설정모드에서는 계속 전송 한다 if (var.getFlag(FLAG_SETUP) == true) { //EEP정보 전송 SendSetupInfo(); } updatetime = millis(); } //입력값 감지 190319 CheckReceiveS0(); CheckReceiveS1(); } void HmiClass::SendIOStatus() { //전송데이터처리 byte payload[29]; //IO4바이트(uint32), A0~A3 A는 각 2바이트(uint16) byte payidx = 0; payload[payidx++] = '@'; //@ payload[payidx++] = '@'; //@ payload[payidx++] = 10; //데이터 길이 payload[payidx++] = 'I'; //49=I(IO) payload[payidx++] = (byte)(var.IOData >> 0); //INPUT(16) payload[payidx++] = (byte)(var.IOData >> 8); //OUTPUT(16) payload[payidx++] = (byte)(var.IOData >> 16); payload[payidx++] = (byte)(var.IOData >> 24); uint32_t flagValue = var.getFlagValue(); payload[payidx++] = (byte)(flagValue >> 0); //FLAG (0~31) payload[payidx++] = (byte)(flagValue >> 8); payload[payidx++] = (byte)(flagValue >> 16); payload[payidx++] = (byte)(flagValue >> 24); //쓰레드진행시간 payload[payidx++] = (byte)var.runtime; //checksum byte checksum = 0; for (int i = 3; i < payidx; i++) checksum = checksum ^ payload[i]; payload[payidx++] = checksum; payload[payidx++] = 0x0D; payload[payidx++] = 0x0A; //Serial.print("Send Payload len="); //Serial.println(payidx); hmiSerial.write(payload, payidx); hmiSerial.flush(); //20190325 - 1번포트로 미러링 //dbgSerial.write(payload, sizeof(payload)); //dbgSerial.flush(); } void HmiClass::SendSetupInfo() { //전송데이터처리 byte payload[19]; //IO4바이트(uint32), A0~A3 A는 각 2바이트(uint16) byte payidx = 0; payload[payidx++] = '@'; //@ payload[payidx++] = '@'; //@ payload[payidx++] = 5; //데이터 길이 payload[payidx++] = 'S'; //49=I(IO),T=TEXT,S=SETUP payload[payidx++] = var._eep_iosendinterval; payload[payidx++] = var._eep_resetcount; payload[payidx++] = var._eep_pindir_iH; payload[payidx++] = var._eep_pindir_iL; //checksum byte checksum = 0; for (int i = 3; i < payidx; i++) checksum = checksum ^ payload[i]; payload[payidx++] = checksum; payload[payidx++] = 0x0D; payload[payidx++] = 0x0A; //Serial.print("Send Payload len="); //Serial.println(sizeof(payload)); hmiSerial.write(payload, sizeof(payload)); hmiSerial.flush(); //20190325 - 1번포트로 미러링 //dbgSerial.write(payload, sizeof(payload)); //dbgSerial.flush(); } void HmiClass::CheckReceiveS0() { //수신데이터가 있는경우에만 처리함 //bool newdata = hmiSerial.available() > 0; //if (newdata) sprint(F("HMI Received Data [")); while (hmiSerial.available() > 0) { incomingByte0 = (char)(hmiSerial.read()); if (STX1S0 == false) { if (incomingByte0 != '@') { STX2S0 = false; ETX1S0 = false; SendMessage(F("ERROR:STX1"), true); continue; } else { STX1S0 = true; ClearTempBuffer0(); Tempbuffer1[bufferIndex0++] = incomingByte0; //Tempbuffer1 += incomingByte; } } else if (STX2S0 == false) { if (bufferIndex0 != 1 || bufferIndex0 < 1 || Tempbuffer1[0] != '@' || incomingByte0 != '@') { STX1S0 = false; ETX1S0 = false; SendMessage(F("ERROR:STX2"), true); continue; } else { STX2S0 = true; Tempbuffer1[bufferIndex0++] = incomingByte0; //Tempbuffer1 += incomingByte; } } else { Tempbuffer1[bufferIndex0++] = incomingByte0; //Tempbuffer1 += incomingByte; //여기서부터는무조건 누적한다. if (bufferIndex0 == 3) { if (Tempbuffer1[0] != 0x40 || Tempbuffer1[1] != '@') { STX1S0 = false; STX2S0 = false; ETX1S0 = false; bufferIndex0 = 0; // = ""; } else LEN1 = incomingByte0; //데이터 길이가온다 } else if (bufferIndex0 == LEN1 + 2 + 1 + 1) //체크섬이 왔다 { CHK1 = incomingByte0; } else if (bufferIndex0 == LEN1 + 2 + 1 + 1 + 1) //ETX1 { if (incomingByte0 != 0x0D) { //ETX가 와야하는데 다른데이터가 왔다 STX1S0 = false; STX2S0 = false; ETX1S0 = false; bufferIndex0 = 0;// SendMessage(F("ERROR:STX3"), true); } } else if (bufferIndex0 == LEN1 + 2 + 1 + 1 + 1 + 1) { //전체길이를 만족햇다. if (incomingByte0 != 0x0A) { //ETX가 와야하는데 다른데이터가 왔다 STX1S0 = false; STX2S0 = false; ETX1S0 = false; //Console.WriteLine("에러 모두 파기"); bufferIndex0 = 0;// == "";//.Clear(); SendMessage(F("ERROR:STX4"), true); } else { STX1S0 = false; STX2S0 = false; ETX1S0 = false; //임시버퍼의 데이터를 수신데이터 변수에 넣는다 //memcpy(buffer.c_str(), Tempbuffer1.c_str(), sizeof(Tempbuffer1)); //Tempbuffer1.toCharArray() //buffer = Tempbuffer1; Parser(bufferIndex0); bufferIndex0 = 0; //Tempbuffer1[0] = 0; //첫비트에 nullstring 을 넣는다 //var.runCommand( parser(buffer1, addMsg1, 0); } } } ////stx ,etx 는 hex 처리하고 번호와 값을 ascii처리함 //if (incomingByte == 0x02) buffer = ""; //else if (incomingByte == 0x03) //{ // //ETX값이나 전체 길이가 4가아니라면 추가해야함 // uint8_t butNo = (uint8_t)(buffer.substring(0, 3).toInt()); // uint8_t butValue = (uint8_t)(buffer.substring(3, 4).toInt()); // //remote 명령과 공유하기 위해서 util로 이동 // var.runCommand((eCommand)butNo, butValue,0); //NewMsgEvent(butNo, butValue); // break; //} //else{ // buffer += (char)incomingByte; //문자를 누적시킨다. // if (buffer.length() > 10) { // sprintln(F("HMI buffer Over error")); // buffer = ""; // } //} } //if (newdata) sprintln("]"); } void HmiClass::CheckReceiveS1() { //수신데이터가 있는경우에만 처리함 //bool newdata = dbgSerial.available() > 0; //if (newdata) sprint(F("HMI Received Data [")); while (dbgSerial.available() > 0) { incomingByte1 = (char)(dbgSerial.read()); if(incomingByte1 == 0x0A) //if newline { String cmd = ""; for(int i = 0 ; i < bufferIndex1;i++) { cmd += String((char)Tempbuffer1[i]); } if(cmd.equals("UP")||cmd.equals("up")) { Serial.println("User command : z-up"); mot.SetZRun(ZRUN_UP); } else if(cmd.equals("DN")||cmd.equals("dn")) { Serial.println("User command : z-down"); mot.SetZRun(ZRUN_DN); } else if(cmd.equals("STOP")||cmd.equals("stop")) { Serial.println("User command : z-stop"); mot.SetZRun(ZRUN_STOP); } else{ Serial.print("Unknown Command : "); Serial.println(cmd); } bufferIndex1 = 0; } else if(bufferIndex1 > 99) { Serial.println(F("recv1 length error(>99")); bufferIndex1 = 0; } else { Tempbuffer1[bufferIndex1++] = incomingByte1; //Tempbuffer1 += incomingByte; } } //if (newdata) sprintln("]"); } /* void HmiClass::CheckReceiveS1_Backup_221117() { //수신데이터가 있는경우에만 처리함 bool newdata = dbgSerial.available() > 0; //if (newdata) sprint(F("HMI Received Data [")); while (dbgSerial.available() > 0) { incomingByte1 = (char)(dbgSerial.read()); if (STX1S1 == false) { if (incomingByte1 != '@') { STX2S1 = false; ETX1S1 = false; SendMessage(F("ERROR:STX1"), true); continue; } else { STX1S1 = true; ClearTempBuffer1(); Tempbuffer1[bufferIndex1++] = incomingByte1; //Tempbuffer1 += incomingByte; } } else if (STX2S1 == false) { if (bufferIndex1 != 1 || bufferIndex1 < 1 || Tempbuffer1[0] != '@' || incomingByte1 != '@') { STX1S1 = false; ETX1S1 = false; SendMessage(F("ERROR:STX2"), true); continue; } else { STX2S1 = true; Tempbuffer1[bufferIndex1++] = incomingByte1; //Tempbuffer1 += incomingByte; } } else { Tempbuffer1[bufferIndex1++] = incomingByte1; //Tempbuffer1 += incomingByte; //여기서부터는무조건 누적한다. if (bufferIndex1 == 3) { if (Tempbuffer1[0] != 0x40 || Tempbuffer1[1] != '@') { STX1S1 = false; STX2S1 = false; ETX1S1 = false; bufferIndex1 = 0; // = ""; } else LEN1 = incomingByte1; //데이터 길이가온다 } else if (bufferIndex1 == LEN1 + 2 + 1 + 1) //체크섬이 왔다 { CHK1 = incomingByte1; } else if (bufferIndex1 == LEN1 + 2 + 1 + 1 + 1) //ETX1 { if (incomingByte1 != 0x0D) { //ETX가 와야하는데 다른데이터가 왔다 STX1S1 = false; STX2S1 = false; ETX1S1 = false; bufferIndex1 = 0;// SendMessage(F("ERROR:STX3"), true); } } else if (bufferIndex1 == LEN1 + 2 + 1 + 1 + 1 + 1) { //전체길이를 만족햇다. if (incomingByte1 != 0x0A) { //ETX가 와야하는데 다른데이터가 왔다 STX1S1 = false; STX2S1 = false; ETX1S1 = false; //Console.WriteLine("에러 모두 파기"); bufferIndex1 = 0;// == "";//.Clear(); SendMessage(F("ERROR:STX4"), true); } else { STX1S1 = false; STX2S1 = false; ETX1S1 = false; //임시버퍼의 데이터를 수신데이터 변수에 넣는다 //memcpy(buffer.c_str(), Tempbuffer1.c_str(), sizeof(Tempbuffer1)); //Tempbuffer1.toCharArray() //buffer = Tempbuffer1; Parser(bufferIndex1); bufferIndex1 = 0; //Tempbuffer1[0] = 0; //첫비트에 nullstring 을 넣는다 //var.runCommand( parser(buffer1, addMsg1, 0); } } } ////stx ,etx 는 hex 처리하고 번호와 값을 ascii처리함 //if (incomingByte == 0x02) buffer = ""; //else if (incomingByte == 0x03) //{ // //ETX값이나 전체 길이가 4가아니라면 추가해야함 // uint8_t butNo = (uint8_t)(buffer.substring(0, 3).toInt()); // uint8_t butValue = (uint8_t)(buffer.substring(3, 4).toInt()); // //remote 명령과 공유하기 위해서 util로 이동 // var.runCommand((eCommand)butNo, butValue,0); //NewMsgEvent(butNo, butValue); // break; //} //else{ // buffer += (char)incomingByte; //문자를 누적시킨다. // if (buffer.length() > 10) { // sprintln(F("HMI buffer Over error")); // buffer = ""; // } //} } //if (newdata) sprintln("]"); } */ void HmiClass::Parser(byte bufferIndex) { Serial.println("Remote Command Parse"); //데이터를 분석해야 함 if (Tempbuffer1[0] == '@' && Tempbuffer1[1] == '@' && Tempbuffer1[bufferIndex - 2] == 0x0D && Tempbuffer1[bufferIndex - 1] == 0x0A) { byte len = Tempbuffer1[2]; byte chk = Tempbuffer1[len + 3]; if (bufferIndex != len + 6) { String msg = ("===>Frame length error len="); msg += String(bufferIndex); msg += (",receive="); msg += String(len + 6); SendMessage(msg, true); } else { //체크섬확인 byte cs = 0; for (int i = 3; i < (3 + len); i++) cs = cs ^ Tempbuffer1[i]; if (chk != cs) { String msg = ("===>checksum error calc="); msg.concat( String(cs)); msg.concat("receive="); msg.concat(String(chk)); SendMessage(msg, true); } else { //체크섬일치 byte command = Tempbuffer1[3]; byte param1 = Tempbuffer1[4]; byte param2 = Tempbuffer1[5]; var.runCommand((eCommand)command, param1, param2); } } } else { //프레임이 이상하다. //sprintln("===>Frame error stx, etx"); SendMessage("==>Frame error no stx,etx", true); } } void HmiClass::ClearTempBuffer0() { LEN0 = 0; bufferIndex0 = 0; memcpy(Tempbuffer0, 0, sizeof(Tempbuffer0)); } void HmiClass::ClearTempBuffer1() { LEN1 = 0; bufferIndex1 = 0; memcpy(Tempbuffer1, 0, sizeof(Tempbuffer1)); } void HmiClass::SendMessage(String message, bool isError) { if(message.equals(hmimessage)) { //동일메세지가 왓다면 1초이내로 다시 전송하지 못하게 한다. if(hmimessagerepeat == 0 || hmimessagerepeat > millis()) hmimessagerepeat = millis(); hmimessagetime = millis()-hmimessagerepeat; if(hmimessagetime < 999) return; } else{ hmimessagerepeat = millis(); hmimessage = message; } // test = len 4 , totals 4+4=8 // @ @ 6 T 0 t e s t chk \r \n byte totalLength = message.length() + 8; byte payload[100]; //IO4바이트(uint32), A0~A3 A는 각 2바이트(uint16) byte payidx = 0; payload[payidx++] = '@'; //@ payload[payidx++] = '@'; //@ payload[payidx++] = message.length() + 2; //데이터 길이 payload[payidx++] = 'T'; payload[payidx++] = isError; //오류여부 for (int i = 0; i < message.length(); i++) { payload[payidx++] = message[i]; } //checksum byte checksum = 0; for (int i = 3; i < (3 + message.length() + 2); i++) checksum = checksum ^ payload[i]; payload[payidx++] = checksum; payload[payidx++] = 0x0D; payload[payidx++] = 0x0A; hmiSerial.write(payload, totalLength); hmiSerial.flush(); //20190325 - 1번포트로 미러링 dbgSerial.println(message); //dbgSerial.write(message, message.length); //dbgSerial.flush(); } bool HmiClass::SendValue(char msg, uint32_t value) { byte totalLength = 11; byte payload[100]; //IO4바이트(uint32), A0~A3 A는 각 2바이트(uint16) byte payidx = 0; payload[payidx++] = '@'; //@ payload[payidx++] = '@'; //@ payload[payidx++] = 6; //데이터 길이 payload[payidx++] = 'V'; payload[payidx++] = msg; //값종류 payload[payidx++] = (byte)(value >> 0); payload[payidx++] = (byte)(value >> 8); payload[payidx++] = (byte)(value >> 16); payload[payidx++] = (byte)(value >> 24); //checksum byte checksum = 0; for (int i = 3; i < (3 + 4 + 2); i++) checksum = checksum ^ payload[i]; payload[payidx++] = checksum; payload[payidx++] = 0x0D; payload[payidx++] = 0x0C; hmiSerial.write(payload, totalLength); hmiSerial.flush(); //20190325 - 1번포트로 미러링 dbgSerial.write(payload, totalLength); dbgSerial.flush(); } HmiClass hmi;