지난번에 통합게시판에 제가
'아두이노 와이파이 쉴드를 이용해서 프로세싱과의 연동은 어떻게 하나요?' 라는 제목으로 질문을 올렸습니다.
링크 : 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;
}
}
|