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

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

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

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

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

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

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

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

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

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

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

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

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

ard.sendDigital();

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

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

#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;
}

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

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

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

아두이노에서 시리얼로 "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, 문자열 파싱 등으로 검색하시면 많은 자료가 나옵니다.
이렇게 정확한 값을 걸러내는 일이 생기게 되는데요, 한번 해두시면 두루두루 쓸 일이 많이 있을 겁니다.

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

1 Like

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

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

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

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

cout << char(myByte); 

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

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