정보나눔

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

아두이노간 블루투스 통신
고덕윤 | 2015-12-08
아두이노 우노2개를 가지고 블루투스를 각각 연결시킨 후 데이터를 주고 받을수 있도록 코드를 짜보고 있습니다.
마스터 블루투스 부분에는 스위치2개와 포텐셔미터1개가 있고 스위치2개를 가지고 슬레이브에 있는 LED 2개를 
ON/OFF 할 예정입니다. 그리고 마스터에 있는 포텐셔미터를 가지고 슬레이브에 있는 서보모터 각도를 조절할 생각입니다.
 
아래는 송신부와 수신부 코드입니다.
<송신부>
#include <SoftwareSerial.h>
 
SoftwareSerial BTSerial(2,3);
 
int shift1 = 13;
int shift2 = 12;
 
void setup() {
  BTSerial.begin(9600);
 
  pinMode(shift1, INPUT_PULLUP);
  pinMode(shift2, INPUT_PULLUP);
}
 
void loop() {
  int state1=digitalRead(shift1);
  int state2=digitalRead(shift2);
  int a=analogRead(A0);
  int aa=map(a,0,1023,4,8);
  if(state1 == LOW) 
  {
    BTSerial.print('1');
    BTSerial.write(state1);
    delay(100);
  }
 
  else if(state2 == LOW)
  {
    BTSerial.print('2');
    BTSerial.write(state2);
    delay(100); 
  }
    else if(state2 == HIGH || state1==HIGH)
  {
    BTSerial.print('S'); 
  }
  else if(aa>3)
  {
    BTSerial.print('M');
    BTSerial.write(aa);
    delay(100);
  }
}
 
<수신부>
#include <SoftwareSerial.h>
#include <Servo.h>
 
SoftwareSerial BTSerial(2,3);
Servo myservo;
 
int changeDirection = 0; 
int led1=13;
int led2=12;
 
void setup() {
  BTSerial.begin(9600);
  Serial.begin(9600);
  myservo.attach(9);
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
}
 
void loop() {
   
  if(BTSerial.available())
  {
    char ch = BTSerial.read();
 
  switch(ch)
  {
    case '1':
    {
      digitalWrite(led2,LOW);
      unsigned char motorSpead = BTSerial.read();
      digitalWrite(led1,motorSpead);
 
    }
    break;
 
    case '2':
    {
      digitalWrite(led1,LOW);
      unsigned char motor = BTSerial.read(); 
      digitalWrite(led2,motor);
 
    }
    break;
 
  case 'S':
    {
      digitalWrite(led1,LOW);
      digitalWrite(led2,LOW);
    }
    break;
    
    case 'M':
    {
      unsigned char angle = BTSerial.read();
      if(angle>51 && angle<57 ){
      int angle1=angle;
      int angle2=map(angle1,52,56,0,90);
      myservo.write(angle2);
      delay(15);
      }
      }
          break;
    }
  }
  }
 
스위치2개를 이용해 LED2개를 ON/OFF 시키는 부분은 잘 작동합니다. 하지만 서보모터의 경우 계속해서 혼자서 왔다갔다하네요.... 
  int aa=map(a,0,1023,4,8); 
송신부에서 이렇게 map 함수를 사용한 이유는 스위치가 눌린 상태에서 동시에 서보모터를 작동시키도록 하기 위해서입니다.
스위치의 경우 0과 1을 주기 때문에 일부러 4~8로 잡았습니다.
      unsigned char angle = BTSerial.read();
   if(angle>51 && angle<57 ){
      int angle1=angle;
      int angle2=map(angle1,52,56,0,90);
      myservo.write(angle2);
      delay(15);
      }
수신부에서 angle을 >51, <57 한 이유는 송신부에서 값을 4~8을 주기때문에 아스키코드로 값이 들어와 저렇게 조건문을 달았습니다. 그후 각도를 0~90도로 map함수로 바꾸었습니다.
 
위 함수에서 어디서 잘못되었는지 암만 고민해봐도 답이 나오질 않아 답변을 구하고자 질문을 올렸습니다..
좋은 답변 부탁드립니다..
프로필사진

수박쨈 2015-12-08 14:56:35

소스가 뭔가 이상한거 같은데요...

 

일단 송신부의 조건문에서 else if(aa>3){} 이부분은 절대 실행될 수 없습니다.

왜냐하면 윗 부분의 조건에서 이미 참 조건을 만족하고 있기 때문이죠.

if/else if문은 모든 조건문 중에서 하나의 조건만 실행하고 나머지 조건은 다 무시하게 되는데 

위 조건에서 스위치가 눌리거나 눌리지 않거나 두 가지의 경우를 모두 포함하고 있기 때문에 맨 아래의 조건은 절대 실행될 수 없습니다. (1번 스위치가 눌리거나, 2번 스위치가 눌리거나, 1번 이나 2번 스위치가 눌리지 않거나) 

 

그리고 저도 헷갈리는데 값을 전달하실때 int값으로 전달하시고 그 값을 unsigned char값으로 변환하는데 int값을 char값으로 변환할 경우

위의 소스에서 4~8의 값은 52~56의 숫자가 될 수 없습니다. 

아스키 코드에서 int값이 52~56이 char값으로 변환했을때가 4~8의 값이 됩니다. 반대로 적으신거 같네요..

프로필사진

고덕윤 2015-12-08 21:39:06

혹시 약간의 힌트를 주실수 있으신가요? 어떤식으로 접근해야되는지..

프로필사진

수박쨈 2015-12-09 13:46:24

서보모터가 혼자 움직이는 이유에 대해서는 무엇때문에 움직이는지 그 값을 시리얼모니터에 출력하는 방법으로 디버깅을 해보셔야 할거 같습니다.

 

일단 위에서 if/else if문으로 모든 조건문을 하나로 묶어서 지정했는데 스위치1이 눌리는 일과 스위치2가 눌리는 일, 포텐셔미터가 돌아가는 일은 각각 별개의 일입니다.(이 말은 스위치1이 눌리는 작업이 스위치2가 눌리거나 눌리지 않거나 하는 상황에 영향을 미치지 않는다는 말입니다.) 독립적인 일이기 때문에 if문또한 if/else if문이 아닌 각각을 if문으로 지정하여 조건문으로 만들어야 합니다.

 

그리고 아스키 코드값은 송신부에서 수신부로 전달될 때 int값으로 4~8사이의 값이 전달되는 데 밑에 아스키코드표를 아시겠지만 

int 4~8의 값을 전달될 때 전혀 다른 문자로 출력됩니다.(지금은 반대로 되있습니다.)

그 값으로 전달하시려면 int가 아닌 Byte으로의 전달이 더 적당해 보입니다.

이전글   |    사운드센서로 측정되는 소리량을 5개의 LED로 제어하고싶은데 질문있습니다.... 2015-12-08
다음글   |    오렌지보드 BLE를 통합적으로 컨트롤 가능한 앱이 있을까요?... 2015-12-09