serialExample 과 아두이노 연결 코드 관련 질문 입니다


#1

serialExample 과 아두이노 연결 코드 관련 질문 입니다.

제가 쓰고 있는 윈도우10의 비쥬얼스튜디오2017 에서

OF communication - firmataExample 과 serialExample 안에 소스코드 설명이 잘되어 있는게 없을까요?

아무리 http://openframeworks.cc/documentation/communication/ofArduino/ 에서 보아도 이해를 할 수가 없습니다.

제가 원하는건 led를 켜거나 또는 센서를통해 숫자를 받는것인데 매우 어렵습니다.

아두이노와 C++은 어느정도 이해하고 있습니다.


#2

연결은 보통 쉽게 가능합니다만, 내용은 좀 길어서 링크를 보시는게 좋을 듯 합니다.

https://www.sparkfun.com/tutorials/318

여기서 Step 3. 정도에 적당한 oF 코드와 Arduino 코드를 찾을 수 있겠네요.


#3

제가 찾아봤던 내용입니다
readbyte, readbytes 에 관련된 내용은 없습니다. 도움이 되지 않았습니다


#4

저의 경우에는 oF의 Firmata 예제 처럼.

ard.getDigital(pinNum));
ard.getAnalog(pinNum));

ard.sendDigital();

로 Arduino 신호를 받거나 보내는 방법으로 사용했었습니다.


#5

저는 아두이노에서 시리얼로 값을 받아서 사용하는데 이 부분도 잘 안되셨나요?


#6

#include “ofApp.h”
#include
#include

using namespace std;

//--------------------------------------------------------------
void ofApp::setup() {

mySerial.listDevices();
vector <ofSerialDeviceInfo> deviceList = mySerial.getDeviceList();

mySerial.setup("COM3", 9600);

}

//--------------------------------------------------------------
void ofApp::update() {

}

//--------------------------------------------------------------
void ofApp::draw() {
int myByte;
myByte = mySerial.readByte();
cout << char(myByte) << endl;
}

적어주신 내용은 이해가 되지않아 하다하다 겨우 숫자는 받아지는데 불안정? 하여 계속 방법을 찾는중입니다.
감사합니다


#7

네 아두이노에서 가변저항을 이용하여 아날로그0번을 통해 값을 받는게 쉽지 않다가 겨우 값이 받아지긴하나
이상하게 데이터가 받아져서 올바른 데이터 값을 받기위해 방법을 찾고 있습니다.
코드는 위에 올려놨습니다.


#8

버퍼를 만들어 주는 것이 좋아요. 통신을 하면 값을 놓치는 경우가 많습니다.

아두이노에서 시리얼로 "12345"를 연속해서 보낸다고 했을 때

Serial.print("12345"); //loop에 넣고 연속해서 보내는 것으로 테스트 했습니다.

readByte()는 글씨를 하나하나 받기 때문에 1,2,3,4,5 이렇게 받아오는 것이 이상적이지만
1,4,5 이런 식으로 띄엄 띄엄 받아오게 될 거에요. 약간의 속도차 때문이 아닌가 싶어요.

readBytes를 쓰시는 것이 좋고, 코드를 적어둘께요.


#include "ofApp.h"

void ofApp::setup(){
  serial.listDevices();
  serial.setup(0, 9600);
}

void ofApp::update(){
     unsigned char tmp[20] = {}; //시리얼 값을 받아오기 위한 버퍼를 만들어 둔다. 배열 length는 20
     
     if(serial.available()){
        serial.readBytes(tmp, 20); //20짜리 length로 받아온다.
        cout << tmp << endl;
     }
     serial.flush();
}

저렇게 하면 아래와 같이 될 거에요.

1234512345123451
2345123451234512
345123451234512

이럴 경우에는 구분자(delimiter)라는 것을 사용합니다. 송신하는 문자열 중간 중간에 넣어서 파싱할 때 사용하는데요, 문장을 12345라고 보내는 것이 아니라 *12345! 이런식으로 해서 * 다음부터 ! 까지 문장인 것으로 판단하곤 합니다.
예로 좌표 x:123 y:234 z:456를 “123,456,789” 으로 보내고 쉼표로 나누기도 하고요.

아두이노에서 이렇게 보낸다고 하면

  Serial.print("*12345!");

of에서 받았을 때 출력은 이렇게 될테고

*12345!*12345!*12345!*1
2345!*12345!*12345!*12
345!*12345!*12345!*12

of에서 파싱을 나름 해봅니다.

void ofApp::update(){
    unsigned char tmp[20] = {}; //시리얼 값을 받아오기 위한 버퍼를 만들어 둔다. 배열 length는 20으로 해보겠습니다.
    vector <char> num; // 값을 저장하기 위한 char형 벡터입니다.
    bool isStart = false;
    bool isEnd = false;
    
    if(serial.available()){ //20짜리 length로 받아온다.
        serial.readBytes(tmp, 20);
        
        for(int i=0; i<20; i++){ //캐릭터 배열 크기만큼 for문을 돌리고
            if(tmp[i] == '*'){ // 중간에 시작을 알리는 '*'이 있으면
                isStart = true; //시작임을 알리고
            }else if(tmp[i] == '!'){ //중간에 끝을 알리는 '!'이 있으면
                isEnd = true; //값의 끝임을 알리고
            }else{
                if(isStart && !isEnd){ //시작은 했으나 끝나지 않으면
                    if(i == 19)
                        num.clear(); //for문을 끝까지 다 돌았는데 끝나지 않으면 벡터 num을 비웁니다.
                    else
                        num.push_back(tmp[i]); //값을 계속 넣어줍니다.
                }
            }
        }
        
//이후 값을 false로 바꿔 주고
        isStart = false; 
        isEnd = false;

//벡터에 값이 있는 상태라면 벡터의 크기만큼 값을 출력합니다.
        if(num.size() > 0){
            for(int i=0; i<num.size(); i++){
                cout << num[i];
            }
            cout << endl;
        }
    }

//벡터와 시리얼을 비움
    num.clear();
    serial.flush();
}

값을 버리는 부분이 있기도 하지만(*송신 값도 여러번 보내주는 것이 좋습니다.) 이러면 * ~ ! 사이의 값이 출력이 될거에요.
string으로 변환하여 연산자를 쓰는 방법도 있고 다양한 방법이 있지만 이해하기 좋도록 코드를 짜봤어요.
delimiter 또는 c++ string parsing, 문자열 파싱 등으로 검색하시면 많은 자료가 나옵니다.
이렇게 정확한 값을 걸러내는 일이 생기게 되는데요, 한번 해두시면 두루두루 쓸 일이 많이 있을 겁니다.

다른 방법이 있으신 분들도 공유했으면 좋겠어요.


#9

int myByte = mySerial.readByte();
cout << char(myByte) << endl;

감사합니다 하지만 위 같이 draw 에 값을 받았더니 0~1023 값은 들어오나
1
0
2
3
으로 들어오는것을
1023 하는방법이 없을까요?

작성해주신 코드는 꾸준히 보면서 연구중입니다 너무 감사드립니다 :slight_smile: 행복한 하루 되십시오~


#10

endl; 은 줄 바꿈을 의미합니다.

cout << char(myByte); 

이렇게 쓰면 줄이 바뀌지 않고 옆으로 계속 붙어서 출력이 되긴 할 것입니다.
다만 적절한 때에 줄을 바꾸셔야 합니다.


#11

Subong_Jeong, jeonghopark
두분 정말 많은 도움 감사드립니다 :slight_smile: