정보나눔

오픈소스하드웨어 프로젝트에 대한 다양한 정보를 나누는 공간입니다.

아두이노 와이파이 쉴드를 통한 프로세싱과의 연동2
김진하 | 2015-11-10

지난번에 통합게시판에 제가

'아두이노 와이파이 쉴드를 이용해서 프로세싱과의 연동은 어떻게 하나요?' 라는 제목으로 질문을 올렸습니다.

링크 : http://kocoafab.cc/fboard/287

(수박쨈님 께서 친절하게 답해 주셨습니다. 수박쨈님 정말 감사합니다!)

 

근데 사용하다 보니 새로운 문제를 발견했는데ㅜㅜ 댓글로 또 질문드리기엔 좀 그래서 

게시판에 새 글로 남깁니다.

 

제가 하고자 하는 프로젝트는 RFID 태그를 찍으면 그 정보를 와이파이 쉴드를 통해서 프로세싱으로 보내는 것입니다.

 

수박쨈님이 알려주신 방식은 아두이노에서 client를 생성해서 client.println(RIFDTag) 명령어를 입력하고 (여기서 RFIDTag는 string 변수)

프로세싱에서는 그 client에서 readString() 함수를 통해 data = c.readString()로 읽어 들이는 것이었습니다.

 

테스트 결과 잘 작동하는 것을 확인했는데요, 문제는 안정성입니다. 즉 작동하다가 프로세싱 쪽에서 갑자기 접속이 끊기는 경우가 생깁니다...

아래 코드는 아두이노 전체 코드에서 client에 정보를 입력하는 부분과 관련된 부분입니다. 

 

void loop(){

.....// 이 부분은 RIFDTag 정보를 읽어오는 것과 관련


Adafruit_CC3000_ClientRef client = httpServer.available();
  
  if (client) {  // 클라이언트를 수신 시
    //Serial.println("new client");  // 클라이언트 접속 확인 메시지 출력
    boolean currentLineIsBlank = true;

    while (client.connected () && SerialReading) { 
      if (client.available()) {
        //Serial.println("client connected");
        char c = client.read();
        // 문자의 끝을 입력 받으면 http 요청이 종료되고, 답신을 보낼 수 있습니다.
        if (c == '\n' && currentLineIsBlank) {
          Serial.println("new Client");
          Serial.println(RFIDTag);
          client.println(RFIDTag);  
          break;
        }
        if (c == '\n') { 
          currentLineIsBlank = true;
        }

        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1000);
  }
}

 

위 코드에서 

while (client.connected () && SerialReading)

라는 명령어에서 SerialReading이라는 boolean Type 변수가 있습니다.

이 변수는 제가 설정한 것인데 이에 대한 설명은 아래에서 하겠습니다.

 

 

 

다음은 프로세싱 코드 입니다.

 

 

import processing.net.*;

Client c;
String data;

void setup() {
  size(200, 200);
  background(50);
  fill(200);
  c = new Client(this, "192.168.0.5", 80); 
  c.write("GET / HTTP/1.1\n"); 
  c.write("Host: processing.org\n\n"); 
}

void draw() {
  if (c.available() > 0) { 
    data = c.readString(); 
    println(data);
  }
  delay(1000);
  c.write("GET / HTTP/1.1\n"); 
  c.write("Host: processing.org\n\n");
}

 

 

위 코드를 사용 해서 RFID 태그를 바꿔가면서 테스트 하다보면 갑자기 프로세싱 쪽에서 다음과 같은 error가 출력이 되면서 접속이 끊기게 됩니다.

 

 

 

아두이노와 프로세싱 코드를 보시면 아래와 같이 둘 다 1초간 지연시키는 기능이 있습니다.

delay(1000);

RFID 태그를 처리하고 와이파이로 보내는데 시간이 걸릴 것 같아서 일부러 아두이노/프로세싱 둘 다 1초 지연 시키는 기능을 넣었습니다.

제 생각엔 이것 때문에 아두이노 쪽에서 RFID tag 를 바꾸는 어떤 순간에 1초 딜레이로 인해서 프로세싱과 어긋나면서 접속이 끊기는 것 같은데...

시간을 바꿔가면서 이것저것 시도해보는데 잘 안되네요 ㅜㅜ

혹시 이거에 대해서 아시는 분은 도와주실 수 있나요?? 

 

 

참고로 저는 HZ 1050이라는 RFID 센서를 사용합니다.

코코아팹에도 RFID에 대한 튜토리얼이 있는데요(http://kocoafab.cc/tutorial/view/142)

HZ 1050은 튜토리얼에 나온 ID-12LA와 다르게 태그를 센서에 가까이 대면 센서가 계속해서 태그 값을 읽어 들이는 것입니다.

즉 튜토리얼에 나온 코드를 그대로 사용한다면 ID-12LA는 태그 값을 읽는 코드가 한번만 실행되는 반면

HZ 1050은 계속해서 태그 정보가 출력이 됩니다. 

 

그래서 태그 정보를 한번만 읽게 하기 위해서 부가적인 작업을 추가하였습니다.

먼저 태그를 읽어오면 그 정보를 oldTag라고 저장해서 실시간으로 읽어 오는 Tag 정보와 비교합니다.

만약 두 개가 일치한다면 A라는 Tag가 계속해서 센서 주변에 있다는 뜻이고 위에서 설명한 SerialReading = false 로 합니다.

일치하지 않다면 다른 Tag 가 들어왔다는 의미 이기 때문에 새로운 Tag 정보를 출력하고 다시 그것을 oldTag로 저장합니다. 그리고 SerialReading = true 로 하여 정보 출력 함수를 한번만 호출하게 합니다.

 

이런 식으로 해서 A 태그가 들어오면 출력을 한번만 하고 

만약 태그를 센서에서 치우면 null 태그 정보가 출력이 되게끔 코드를 구현했습니다. 

 

이 과정이 그렇게 오래 걸릴 것 같진 않은데... 이 과정들을 처리하다가 오래 걸려서 와이파이로 전송하는 시간과 

프로세싱에서 읽어 오는 시간이 어긋나는 것일까요...?

 

 

아래는 전체 아두이노 코드 입니다. 

 


#include <Adafruit_CC3000.h>
#include <SPI.h>
#include "utility/debug.h"
#include "utility/socket.h"
#include <SoftwareSerial.h>


// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ   3
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10

Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIVIDER); // you can change this clock speed

#define WLAN_SSID "iptime_mini_gammazx" // cannot be longer than 32 characters!
#define WLAN_PASS "fkaakzx59"

// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY WLAN_SEC_WPA2

#define LISTEN_PORT 80 // What TCP port to listen on for connections. 
// The HTTP protocol uses port 80 by default.

// HTTP version.
#define TIMEOUT_MS 500 // Amount of time in milliseconds to wait for
// an incoming request to finish. Don't set this
// too high or your server could be slow to respond.
Adafruit_CC3000_Server httpServer(LISTEN_PORT);


SoftwareSerial rSerial(7,4);

// ------------ Part 2 ---------------

int tag1[4] = {0, 95, 87, 203};   // RFID 태그의 ID입니다. 
int tag2[4] = {0, 146, 138, 168};
int tag3[4] = {0, 146, 207, 160};
int tag4[4] = {0, 134, 233, 58};

int led = 13;
int TestTag[4] = {0, 0, 0, 1}; //  TestTag를 선언합니다
int oldTag[4] = {0, 0, 0, 2};
int zeroTag[4] = {0,0,0,0};

boolean SerialReading = true;

String RFIDTag = "null";

void setup(){
  Serial.begin(9600);
  rSerial.begin(9600); 

  Serial.println(F("Hello, CC3000!\n"));
  
  // Initialise the module
  Serial.println(F("\nInitializing..."));
  if (!cc3000.begin())
  {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    while(1);
  }
  Serial.print(F("\nAttempting to connect to ")); Serial.println(WLAN_SSID);
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
  while(1);
  }
  Serial.println(F("Connected!"));
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())
  {
   delay(100); // ToDo: Insert a DHCP timeout!
  }
  // Display the IP address DNS, Gateway, etc.
  while (! displayConnectionDetails()) {
  delay(1000);
  }
  // ******************************************************
  // You can safely remove this to save some flash memory!
  // *****************************************************  
  // Start listening for connections
    httpServer.begin();
  Serial.println(F("Listening for connections..."));
  
}

void loop(){
  
  int index =0 ;

  while(rSerial.available() && index < 4) {
    
    //int readByte = Serial.read(); // 시리얼 포트에 있는 데이터를 저장합니다.
    int readByte = rSerial.read();
    TestTag[index] = readByte;
    //Serial.println(TestTag[index]); // RFID 태그의 ID를 출력합니다.
    index++;
  }

  compareOldTag(TestTag, oldTag);

  delay(1);
  
  if(SerialReading){
    checkTag(TestTag); // 저장된 태그 ID와 RFID 리더에서 읽은 태그 ID와 일치하는지 확인
  }
  clearTag(TestTag); // 읽어온 태그 ID를 지움


  
  Adafruit_CC3000_ClientRef client = httpServer.available();
  
  if (client) {  // 클라이언트를 수신 시
    //Serial.println("new client");  // 클라이언트 접속 확인 메시지 출력
    boolean currentLineIsBlank = true;

    while (client.connected () && SerialReading) { 
      if (client.available()) {
        //Serial.println("client connected");
        char c = client.read();
        // 문자의 끝을 입력 받으면 http 요청이 종료되고, 답신을 보낼 수 있습니다.
        if (c == '\n' && currentLineIsBlank) {
          Serial.println("new Client");
          Serial.println(RFIDTag);
          client.println(RFIDTag);  
          break;
        }
        if (c == '\n') { 
          currentLineIsBlank = true;
        }

        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1000);
    //delay(1);
  }
}
void checkTag(int tag[]){

 if(compareTag(tag, tag1)){ // 저장된 태그 ID와 읽은 태그 ID를 비교합니다.
    
    RFIDTag = "O";
    for(int i = 0; i<4; i++)
    {
      oldTag[i] = tag[i];
    }
 }  
 else if(compareTag(tag, tag2)){ // 저장된 태그 ID와 읽은 태그 ID를 비교합니다.
    
    RFIDTag = "X";
    for(int i = 0; i<4; i++)
    {
      oldTag[i] = tag[i];
    }
 }
 else if(compareTag(tag, tag3)){
    RFIDTag = "Y";
    for(int i = 0; i<4; i++)
    {
      oldTag[i] = tag[i];
    }
 }
 else if(compareTag(tag, tag4)){
    RFIDTag = "Z";
    for(int i = 0; i<4; i++)
    {
      oldTag[i] = tag[i];
    }
 }
 else if(compareTag(tag, zeroTag)){
    RFIDTag = "null";
    for(int i = 0; i<4; i++)
    {
      oldTag[i] = tag[i];
    }
 }
}

void compareOldTag(int one[], int two[]){ // 현재 계속 읽고 있는 아이디 값이랑 같으면 while문 멈추게 하기 위
  for (int i=0; i < 4; i++){  
    if(one[i]!=two[i]) { 
      SerialReading = true;
    }
    else{
      SerialReading = false; // 전부 일치할 경우 SesonrReading을 false로 주어서 while문 멈춘다
    }
  } 
}

void clearTag(int tag[]){   // 읽은 태그 ID를 초기화
  for(int i =0; i < 4; i++){
    tag[i] = 0;
  }
}

boolean compareTag(int one[], int two[]){ // 읽은 태그 ID와 저장된 태그 ID를 비교
  for (int i=0; i < 4; i++){  // 읽은 태그와 저장된 태그 ID를 한자리 씩 비교
    if(one[i]!=two[i]) { // 제 태그 ID의 앞자리가 이상한 값이 들어와서 수정

      return false; // 하나라도 다르면 다른 태그 ID로 정함
    }
  }
  return true; // 전부 일치할 경우 일치하는 상태 값을 보냄
}

boolean checkZeroTag(int tag[]){
  int countZero = 0;
  for (int i = 0; i<4; i++){
    if(tag[i] == 0){
      countZero++;
      }
  }
  if(countZero == 4) { // If Tag is zero 
    return true;
    SerialReading = true;
  }
  else{
    return false; // If Tag is not zero
  }
}


bool displayConnectionDetails(void)
{
  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
  if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
  {
    Serial.println(F("Unable to retrieve the IP Address!\r\n"));
    return false;
  }
  else
  {
    Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
    Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
    Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
    Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
    Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
    Serial.println();
    return true;
  }
}

 

프로필사진

Klant 2015-11-10 10:18:06

안녕하세요! 

우선 질문을 상세히 해주셔서 감사합니다. 덕분에 이해하기가 쉬웠습니다. 

궁금한 점은 현재 소스로 테스트 해보셨을 때 정상적으로 프로세싱에서 RFID tag 정보를 받아오다가 에러가 발생하는 것인가요?

 

 

 

프로필사진

김진하 2015-11-10 10:36:02

네 맞습니다. 제가 화면을 캡쳐를 못 해서 그런데 프로세싱 화면에서

 

null

null

X

X

null

null

Y

Y

 

뭐 이런 식으로 화면이 출력되면서 정상적으로 RFID Tag를 받아오다가 어느 순간 에러가 납니다. 

RFID Tag를 바꾼다거나 특히 한 RFID Tag를 센서에 오랫 동안 접촉 시켜놓았다가 떼는 순간 에러가 잘납니다.

프로필사진

김진하 2015-11-10 10:48:27

사실 어제 밤 늦게까지 해보았는데

생각해보니 굳이 oldTag를 저장하면서 태그 정보를 한 번만 읽게 할 필요는 없는 것 같더라고요.

그냥 센서가 인식하는데로 RFID Tag라는 String 변수를 계속 업데이트만 해주고

RFID Tag를 client에 write만 해주면 되더라고요.

(제가 와이파이 쉴드 없이 테스트 할 때 편하게 하기 위해서 이런 번거로운 작업을 거쳤는데 와이파이 통해서 업데이트 할 때는 굳이 이런 작업을 안 거쳐도 될 것 같아서 생략했습니다.)

 

그리고 프로세싱 쪽에서 delay(3000)로 3초 동안 충분히 기다려 주니까 반응이 즉각적으로 오는 것은 아니지만 그래도 중간에 끊기는 일은 안 생기더라고요! 일단은 그 문제는 해결한 것 같습니다.

 아마도 프로세싱 쪽에서 와이파이 통해서 들어오는 정보를 인식하는데 충분한 시간을 기다려줘야 되는 것 같다는게 제 생각입니다....

 

근데 여기서 새로운 질문이 있는데요 ㅜㅜ

제가 하려는 프로젝트는 프로세싱에서 RFID Tag를 인식 하면 그 반응에 따라 프로세싱에서 다른 작업이 실행 되는 것인데

문제는 delay를 3초동안이나 하면 너무 느리다는 것입니다...  그리고 그 작업이 구현해 놓은 코드가 꽤 길어서 제가 원하는 데로 실행이 잘 안되더라고요...

 

이 문제를 해결할 방법이 있을까요?

꼭 프로세싱에서 delay로 충분히 기다려 줘야 되는건가요?

프로필사진

최승수 2015-11-12 17:31:11

와이파이와의 연동인가요?

프로필사진

최승수 2015-11-12 17:31:11

와이파이와의 연동인가요?

이전글   |    RGB문의드립니다 2015-11-09
다음글   |    오렌지보드BLE 에서 BLE 모듈에 보낼수 있는 모든 AT command 는 어떤것들이 ... 2015-11-10