#include #include "Arduino.h" #define DEBUG bool cstate[3]; // 현재 상태(이전 상태와 비교하여 상태변화를 확인한다) bool pstate[3]; // 이전 상태 bool bchange[3]; //특정핀의 상태가 변경되었는가? unsigned long clicktime[3]; //각 버튼 down 상태의 밀리초를 저장한다(롱 클릭 시간 확인용) unsigned long ontime = 0; unsigned long ledtime = 0; //bool bCharge = false; //클라이언트 7번 bool bHWError = false; //클라이언트 8번 bool bSelected = false; //현재 선택된 클라이언트 (LED가 깜박인다) bool bEnbCall =false; //콜 가능여부 bool runtimeledon=false; String version = "2411291722"; String recvbuffer = ""; uint8_t clientno = 0; uint8_t offmode = 0; uint8_t clickcnt = 0; int pinIn[3] = { 2, 3 , 4 }; int pinOut[3] = { 5, 6 , 7 }; void setup() { delay(2000); #ifdef DEBUG Serial.begin(19200); #endif Serial1.begin(9600); //; Serial.println("Setup Start"); for (int i = 0; i < 3; i++) { pinMode(pinIn[i], INPUT_PULLUP); pinMode(pinOut[i], OUTPUT); digitalWrite(pinOut[i], HIGH); //처음켜지면 ON상태로 한다. cstate[i] = false; pstate[i] = false; clicktime[i] = 0; } //digitalWrite(13,HIGH); /// Serial.println("Serial1 Wait"); #ifdef DEBUG clicktime[0] = millis(); while (!Serial) { unsigned long runtime = millis() - clicktime[0]; if (runtime >= 1000) { //bSerial=false; // Serial.println("Serial1 timeout"); break; } // wait for serial port to connect. Needed for native USB port only } #endif //digitalWrite(13,LOW); clientno = EEPROM.read(0); //내부롬의 0번주소에서 클라이언트 번호를 확인한다. //#ifdef DEBUG Serial.print("AGV Caller v");// 1904020000"); Serial.println(version); Serial.print("ready #"); Serial.print(clientno); Serial.println(); //#endif //초기화 완료되면 oFF 한다. digitalWrite(pinOut[0], LOW); digitalWrite(pinOut[1], LOW); digitalWrite(pinOut[2], LOW); offmode = 0; digitalWrite(13,LOW); } void loop() { #ifdef DEBUG unsigned long runtimeled = millis() -ledtime; if(runtimeled > 200) { if(runtimeledon==true) { digitalWrite(13,LOW); runtimeledon=false; }else{ digitalWrite(13,HIGH); runtimeledon=true; } runtimeled= millis(); } #endif //버튼입력상태를 확인한다. for (int i = 0; i < 3; i++) { cstate[i] = !digitalRead(pinIn[i]); if (cstate[i] != pstate[i]) { /*Serial.print("#"); Serial.print(pinIn[i]); Serial.print(" changed"); Serial.println(cstate[i]);*/ bchange[i] = true; if (cstate[i]) //클릭시 { clicktime[i] = millis(); //Serial.print("SET TIME #"); //Serial.print(i); //Serial.println(); } } } //버튼 상태변화를 감지 if (cstate[0] && cstate[1]) //두버튼이 동시에 눌려있다면 디버그모드 진입여부를 확인한다. { unsigned long time1 = millis() - clicktime[0]; unsigned long time2 = millis() - clicktime[1]; if (time1 > 3000 && time2 > 3000) { if (offmode == 0) { //OFF 상태일때에는 시리얼 버퍼처리를 하지 않는다. offmode = 1; #ifdef DEBUG Serial.println("ENTER MODE SELECT"); #endif } } //동시에 눌려있지만 아직 지정 시간전이므로 처리하지 않는다. } else if (cstate[0] || cstate[1] || cstate[2]) //버튼이 하나만 눌려있을때 { if (offmode == 2) //client set mode { if (cstate[0] && bchange[0]) { clickcnt += 1; #ifdef DEBUG Serial.print("Click Count = "); Serial.println(clickcnt); #endif } else if (cstate[1] && bchange[1]) { //두번째 버튼을 눌렀다면 완료를 의미한다. clientno = clickcnt; SaveNo(); //현재 값을 저장 해준다. //선택된 번호를 깜박임으로 알려준다. delay(100); digitalWrite(pinOut[0], LOW); digitalWrite(pinOut[1], LOW); delay(1000); for (uint8_t i = 1; i <= clientno; i++) { digitalWrite(pinOut[0], HIGH); delay(500); digitalWrite(pinOut[0], LOW); delay(500); } #ifdef DEBUG Serial.print("New Client Complete No="); Serial.println(clientno); #endif offmode = 0; //다시 처음상태로 이동 } } else if (offmode == 3) //off mode { if (bchange[0] || bchange[1]) { Serial1.begin(9600); //re open port #ifdef DEBUG Serial.println("OFF MODE DISABLE -> NORMAL MODE"); #endif offmode = 0; //일반상태로 전환 } } else if (offmode == 1) //mod select { if (bchange[0] && cstate[0]) //0번버튼이 ON 되었다면 번호편집모드로 전환 { #ifdef DEBUG Serial.println("NO. SET MODE"); #endif clickcnt = 0; //클릭횟수를 초기화 offmode = 2; } else if (bchange[1] && cstate[1]) //1번버튼이 ON 되었다면 OFF 모드로 전환 { Serial1.end(); #ifdef DEBUG Serial.println("OFF MODE : Disable Serial for xbee"); #endif offmode = 3; } } else if (offmode == 0) { //일반 모드일때 하나만 눌렸다면 해당 버튼 명령을 전송한다. //uint8_t clientascii = (uint8_t)(clientno + 30); if (bchange[0] && cstate[0]) { #ifndef DEBUG digitalWrite(13,HIGH); delay(200); digitalWrite(13,LOW); #endif Serial1.clearWriteError(); Serial1.write(0x02); Serial1.print(clientno); Serial1.print('1'); //call Serial1.write(0x03); Serial1.flush(); #ifdef DEBUG Serial.print("SEND CALL #"); Serial.println(clientno); #endif } else if (bchange[1] && cstate[1]) { #ifndef DEBUG digitalWrite(13,HIGH); delay(200); digitalWrite(13,LOW); #endif Serial1.clearWriteError(); Serial1.write(0x02); Serial1.print(clientno); Serial1.print('0'); //call Serial1.write(0x03); Serial1.flush(); #ifdef DEBUG Serial.print("SEND CANCEL#"); Serial.println(clientno); #endif } else if (bchange[2] && cstate[2]) //QA진행 버튼이 눌렸을때 { #ifndef DEBUG digitalWrite(13,HIGH); delay(200); digitalWrite(13,LOW); #endif Serial1.clearWriteError(); Serial1.write(0x02); Serial1.print(clientno); Serial1.print('2'); //go qa Serial1.write(0x03); Serial1.flush(); #ifdef DEBUG Serial.print("SEND QA#"); Serial.println(clientno); #endif } } } //Serial.print("mode="); //Serial.println(offmode); //LED상태 조정 switch (offmode) { case 0: //일반 상태값(버튼을 누르면 해당 버튼의 LED를 조정한다) digitalWrite(pinOut[0], cstate[0]); digitalWrite(pinOut[1], cstate[1]); digitalWrite(pinOut[2], cstate[2]); //Serial.print("led 3 stat="); //Serial.println(cstate[2]); break; case 1: //모드 선택 상태( 이때 OK를 누르면 번호셋, CANCEL을 누르면 OFF 상태로) if (digitalRead(pinOut[0]) == true) { digitalWrite(pinOut[1], HIGH); digitalWrite(pinOut[0], LOW); } else { digitalWrite(pinOut[0], HIGH); digitalWrite(pinOut[1], LOW); } delay(100); break; case 2: //클라이언트 번호 설정 모드 - 적색만 깜박이고 녹색의 클릭횟수로 번호를 설정한다. if (digitalRead(pinOut[1]) == true) digitalWrite(pinOut[1], LOW); else digitalWrite(pinOut[1], HIGH); break; delay(100); case 3: //OFF 상태일때에는 LED를 서로 ON/OFF 한다. if (digitalRead(pinOut[0]) == true) { digitalWrite(pinOut[1], LOW); digitalWrite(pinOut[0], LOW); } else { digitalWrite(pinOut[0], HIGH); digitalWrite(pinOut[1], HIGH); } delay(100); } //상태변환 여부를 초기화 if (bchange[0]) pstate[0] = cstate[0]; if (bchange[1]) pstate[1] = cstate[1]; if (bchange[2]) pstate[2] = cstate[2]; bchange[0] = false; bchange[1] = false; bchange[2] = false; //일반모드일때 처리 내역 if (offmode == 0) { unsigned long runtime = millis() - ontime; //CALL가능하면 3번 LED를 ON 한다 230119 if(bEnbCall) { digitalWrite(pinOut[2],HIGH); } else{ if(cstate[2]) digitalWrite(pinOut[2],HIGH); else digitalWrite(pinOut[2],LOW); } //현재 개체가 AGV선택개체라면 LED를 깜박거려서 표시를 해준다.(녹색버튼기준) if (bHWError) { //하드웨어 오류 발생시에는 적색을 깜박거린다.(녹색:OFF) digitalWrite(pinOut[0], LOW); //녹색은 끈다. //적색을 깜박인다.(1초주기로 ON/OFF 한다) bool state = digitalRead(pinOut[1]); if (runtime >= 250) //190319 { if (state) digitalWrite(pinOut[1], LOW); else digitalWrite(pinOut[1], HIGH); ontime = millis(); } } else if (bSelected) { digitalWrite(pinOut[1], HIGH); //적색은 일단 켜둔다. //선택된 개체일때에는 적색은 켜고 녹색은 끔박인다. bool state = digitalRead(pinOut[0]); //500ms 단위로 깜박인다. if (runtime >= 500) //190319 { if (state) digitalWrite(pinOut[0], LOW); else digitalWrite(pinOut[0], HIGH); ontime = millis(); } } else { //선택개체가 아니라면 LED를 모두 OFF해준다. for (int i = 0; i < 2; i++) { if (digitalRead(pinIn[0]) != digitalRead(pinOut[0])) cstate[i] = !cstate[i]; //이전상태값을 반전시켜줌으로 써 다음 루프때 LED가 꺼지게 한다. } } } //외부디버그 명령을 처리한다. #ifdef DEBUG CheckRemoteDebugCommand(); #endif CheckReceiveXbee(); delay(100); } void CheckRemoteDebugCommand() { if (Serial.available() > 0) { int recv = Serial.read(); if (recv == 0x0A || recv == 0x0D) { RunCommand(); recvbuffer = ""; } else { recvbuffer += (char)recv; } } } String buffer = ""; int kitNo = 0; int incomingByte = 0; void CheckReceiveXbee() { //수신된 자료가 잇는지 체크한다. #ifndef DEBUG digitalWrite(13,HIGH); #endif while (Serial1.available() > 0) { incomingByte = Serial1.read(); #ifdef DEBUG Serial.print("[RX]"); Serial.println(incomingByte, HEX); #endif //stx ,etx 는 hex 처리하고 번호와 값을 ascii처리함 if (incomingByte == 0x02) { buffer = ""; } else if (incomingByte == 0x03) { //ETX값이나 전체 길이가 4가아니라면 추가해야함 byte clientno = (byte)(buffer.substring(0, 1).toInt()); char clientval = buffer[1];// .substring(1, 2).toInt()); char enablecall = '0'; //콜가능여부 추가 230119 //데이터가 3바이트라면 콜 가능상태로 전송된 경우이다 230119 if(buffer.length() > 2) { enablecall = buffer[2]; } NewMsgEvent(clientno, clientval,enablecall); break; } else{ buffer += (char)incomingByte; //문자를 누적시킨다. } } #ifndef DEBUG digitalWrite(13,LOW); #endif } /* 190319 */ void NewMsgEvent(uint8_t no, char value,char canCall) { if (no == 1) return; //충전기관련 코드는 처리 하지 않는다. 190417 else if (no == 8) //AGV가 HW에러 발생시 이 값을 전송한다. { if (bHWError == false) bHWError = true; #ifdef DEBUG if (value == '1')//system error { Serial.println("FLAG ON : H/W ERROR"); } else { Serial.println("FLAG ON : AGV MANUAL MODE"); } #endif return; } //그외 나머지 상태에는 오류사항을 해제 해준다. if (bHWError == true) { bHWError = false; #ifdef DEBUG Serial.println("FLAG OFF : H/W ERROR OFF"); #endif } bEnbCall = (canCall == '1'); //누군가가 지정되어있다. if (value == '1') { if (no != clientno) //해당 번호가 내 번호와 일치하지 않는다면 내가 지정된 경우가 아니다. { //서버로부터 어떠한 개체가 켜졌는데. 그게 내가 아니라면 나는 OFF 한다. if (bSelected) bSelected = false; #ifdef DEBUG Serial.print("Selected Off by Another ON No="); Serial.println(no); #endif } else { bSelected = true; //내 번호가 켜졌으므로 선택됨으로 한다. #ifdef DEBUG Serial.print("Selected On No="); Serial.println(no); #endif } } else if (value == '0') //누군가가 OFF 되어있다. { if (no == clientno) { //내가 꺼졋음을 보내왔다. bSelected = false; #ifdef DEBUG Serial.println("Selected Off"); #endif } } } void RunCommand() { Serial.print("Remote Control : "); Serial.println(recvbuffer); if (recvbuffer == "on") { Serial.print("on clientno = "); Serial.println(clientno); NewMsgEvent(clientno, '1','1'); } else if (recvbuffer == "callon") { Serial.print("on clientno = "); Serial.println(clientno); NewMsgEvent(clientno, '0','1'); } else if (recvbuffer == "calloff") { Serial.print("on clientno = "); Serial.println(clientno); NewMsgEvent(clientno, '0','0'); } else if (recvbuffer == "off") { Serial.print("off clientno = "); Serial.println(clientno); NewMsgEvent(clientno, '0','0'); } else if (recvbuffer == "hw") { bHWError = !bHWError; Serial.print("bHWError="); Serial.println(bHWError); } else if (recvbuffer == "set") { Serial1.print("+++"); Serial1.write(0x0D); Serial1.flush(); } else if (recvbuffer == "h") { Serial.println("AGV Caller"); Serial.print("v"); Serial.println(version); Serial.println("=============="); Serial.println("h : help"); Serial.println("on : selected on"); Serial.println("off : selected off"); Serial.println("#1~6 : set client no"); Serial.println("? : get client no"); Serial.println("=============="); } else if (recvbuffer == "?") { Serial.print("Get Client No : #"); Serial.println(clientno); } else if (recvbuffer.startsWith("#")) { String strNo = recvbuffer.substring(1); clientno = (byte)(strNo.toInt()); SaveNo(); // EEPROM.write(0, clientno); } } void SaveNo() { EEPROM.write(0, clientno); #ifdef DEBUG Serial.print("Save Client No : #"); Serial.println(clientno); #endif }