본문 바로가기
심화캡스톤

시리얼 통신의 문제점과 해결법 (아두이노 자바 통신 글자 나눠서 수신됨)

by Enhydra lutris 2023. 6. 29.

시리얼 통신의 문제점

1. 데이터가 나뉘어 수신 될 수 있다.

아두이노에서 시리얼 모니터로 확인 할때는 1234 처럼 여러자리 숫자를 송신하면 한번에 수신 된다.

하지만 진짜 시리얼 통신을 하다보면 수신이 12 34 1 234 이런 식으로 나눠서 오는 경우가 있다.

사실 이거는 시리얼 통신의 고질적인 문제인데 시리얼 통신은 데이터를 한번에 쐈다고 그 데이터 전부를 무조건 한번에 다 받아오는 것이 아니다. 한번에 받아올 수도 있고 여러번에 나눠서 받아올 수도 있다.

 

2. 글자가 깨져서 수신 될 수 있다.

내가 보낸 문자가 깨져서 수신될 수 있기 때문에 LRC,CRC를 통해 오류를 검출 해야 한다.

시리얼 통신을 하면서 주의해야 할 점

위에서 말했듯 시리얼 통신은 수신된 데이터에 문제가 있을 수 있다. 따라서 데이터의 유효성 검사를 거친후에 데이터를 사용해야 한다.

 

데이터 나뉘어 지는 문제 해결법

분명 더 좋은 방법이 존재할 것 같지만 구글링해도 딱히 괜찮은 방법을 찾지 못해서 나는 급한대로 아래와 같이 해결했다.

 

아두이노 코드

아래 코드는 로드셀 센서에서 무게를 받아와서 자바로 송신하는 코드이다.

내가 사용한 로드셀 센서는 최대 4자리수까지 출력되는 제품이기 때문에 센서에서 받은 값 앞에 부족한 자릿수 만큼 0을 채워줬다.

#include "HX711.h"
#define calibration_factor 574.3 //캘리브레이션 값
#define DOUT  3 //데이터 핀
#define CLK  2 // 클럭 핀


int value;
HX711 scale(DOUT, CLK);
void setup() {
    Serial.begin(9600);  // 값 모니터링 위해서...
    scale.set_scale(calibration_factor);
    //scale.tare(); //영점잡기. 현재 측정값을 0으로 둔다.
    digitalWrite(PUMP, LOW);
}
void loop() {
    value = (int)scale.get_units();

    if (value <= 0) {
        Serial.print("0000");
    }
    else if (value > 2 && value <= 9) {
        Serial.print("000");
        Serial.print(value);
    }
    else if (value > 9 && value <= 99) {
        Serial.print("00");
        Serial.print(value);
    }
        else if (value > 9 && value <= 99) {
        Serial.print("00");
        Serial.print(value);
    }
    else if (value > 99 && value <= 999) {
        Serial.print("0");
        Serial.print(value);
    }
    else {
        Serial.print(value);
    }
}

자바 코드

아래 코드는 포트에서 받아온 IntputStrream을 이용하여 값을 수신하는 코드이다.

아두이노에서 4글자로 보냈기 때문에 in.avaliable이 4보다 커질 때까지 스레드를 잠깐 멈춘다.

그리고 4글자를 넘어가면 안되기 때문에 len == 4인지 확인한후 데이터를 사용했다.

import java.io.InputStream;

public class SerialReadThread implements Runnable{
    private final InputStream in;

    public SerialReadThread(InputStream in) {
        this.in = in;
    }

    @Override
    public void run() {
        byte[] buffer = new byte[10];
        int len = -1;
        try {
            while ((len = this.in.read(buffer)) > -1) {
                while(in.available() < 4){
                    //센서 값은 4글자로 넘어 오기 때문에 버퍼에 5글자가 채워졌는지 확인 하고 안들어 왔다면 스레드 멈추고 들어올때 까지 기다리기
                    Thread.sleep(1);
                }
                String s = new String(buffer,0,len);
                //len == 4로 시리얼로 받은 데이터가 형식에 맞게 버퍼에 들어왔는지 확인
                if (len == 4) {
                System.out.println("수신 데이터:" + s);
                }
            }
        } catch (Exception e) {}
    }
}

댓글