본문으로 바로가기

저는 한 3년 전쯤에 Python에서 matplotlib에서 그래프에서 애니메이션 효과로 그래프를 그리는 이야기를 했습니다. 그리고, 마우스 대응등 인터략티브한 그래프 이야기를 추가로 했었네요. 그리고 아주 예전에 Python에서 시리얼 통신하는 법에 대한 이야기도 했었죠. 오늘은 시리얼 통신으로 연결된 데이터를 받아서 간편하게 실시간 그래프를 그리는 것에 대한 이야기를 하려고 합니다. 일단, 그 대상으로 아두이노 보드를 잡았습니다. 아두이노 보드는 그냥 PC와 연결만 시켜 두어서 사진으로 보여드리지는 않겠습니다.^^

void setup() {
  	// put your setup code here, to run once:
  	Serial.begin(115200);
}

void loop() {
  	// put your main code here, to run repeatedly:  	
	Serial.println(random(10,20));
	delay(500);
}

먼저 아두이노 프로그램에는 저렇게 그냥 10과 20사이의 랜덤값을 시리얼 통신으로 보내는 프로그램을 만들어 두었습니다. 그리고, 아두이노를 실행하면 뭐~ 끝나는거죠^^

import serial

arduino = serial.Serial('/dev/tty.usbmodem14401', 115200)
y = arduino.readline()

Python에서 시리얼 통신은 저 코드가 전부입니다.^^ 아.. /dev/tty어쩌고는 윈도우 유저는 COM1과 같이 연결된 시리얼 포트 번호를 넣어 두면 됩니다. 저는 맥이라서 저렇게 됩니다. 아무튼, 문제는 저 데이터를 받은 다음 코드 상으로는 y 값이 문제죠^^ 아두이노에서 println 명령으로 보냈기 때문에 줄바뀜 기호가 들어가 있습니다.

터미널에서 실행해서 결과를 보면, b어쩌고로 시작해서 \n으로 끝나네요... 바이트 단위로 들어왔기 때문입니다.

바이트로 들어온 데이터는 decode()를 이용하면 해결됩니다.

뒤의 두 문자(\r\n)는 항상 붙는 거라 저렇게 잘라버리면 됩니다.

그리고서 float을 사용하면 숫자로 변경됩니다.^^ 그럼 이전에 글 앞부분에 이야기드린 애니메이션까지 넣어보죠

import serial
from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np

arduino = serial.Serial('/dev/tty.usbmodem14401', 115200)

fig = plt.figure()
ax = plt.axes(xlim=(0, 50), ylim=(0, 30))
line, = ax.plot([], [], lw=2)

max_points = 50
line, = ax.plot(np.arange(max_points), 
                np.ones(max_points, dtype=np.float)*np.nan, lw=2)

def init():
    return line,

def animate(i):
    y = arduino.readline()
    y = y.decode()[:-2]
    y = float(y)

    old_y = line.get_ydata()
    new_y = np.r_[old_y[1:], y]
    line.set_ydata(new_y)
    return line,

anim = animation.FuncAnimation(fig, animate, init_func=init, frames=200, interval=20, blit=False)

plt.show()

이렇게~ 됩니다. matplotlib의 FuncAnimation 함수를 사용하기 위해 init과 animate 함수를 만들어 두고, animate 함수에서 시리얼통신에서 데이터를 받도록 합니다. 이 코드의 실행 결과는 아래 동영상과 같습니다.

다음에는 아주 재미있는 것을 올려볼께용~^^


댓글을 달아 주세요

  1. BlogIcon 핑구야 날자 2019.07.04 06:43 신고

    파이썬에서 시리얼통신으로 할 수 있는 팁 이군요 오늘도 즐거운 하루 보내세요

  2. BlogIcon 북두협객 2019.07.05 07:20 신고

    코딩을 떡주무르듯 마음대로 주물러서 가지고 노시네요~

  3. 파이썬초보 2019.09.17 01:36

    안녕하세요 제가 지금 위의 코드와 비슷한 코드를 짜고있습니다. 저는 현재 아두이노에서 30000개의 정수형값을 받아와 20 X 1500개의 행렬형태로 만들어 계산작업을 하려 하고 있습니다. 하지만 행렬에 값을 집어 넣을때 계속 쓰레기값이 들어와 에러가 뜹니다. 혹시 이문제에 대해 알고 계신가요???

  4. bluewink 2019.09.19 03:07

    안녕하세요 시리얼 통신으로 받은 데이터를 배열값에 담아 이미지화 시켜 실시간으로 영상을 보려고 합니다. 제 생각은 imshow를 무한루프 돌려서 영상으로 만드려고 하는데 사진이 한장켜지면 거기서 무한루프가 멈춰버립니다. 그리고 사진창을 끄면 다시 무한루프가 돌아갑니다. 어떻게 해야 하죠? 도와주세요

    • BlogIcon PinkWink 2019.09.20 01:28 신고

      글쎄요.. 시리얼통신으로 받아야하나요? TCP/IP 같은 것으로 해야하지 않을까해서요. 시리얼로 사진을 계속 하기 어려울 것 같은데... 잘 모르겠네요.ㅠㅠ.

  5. 힝그 2019.10.21 12:55

    코드에서
    line, = ax.plot([], [], lw=2) 라고 쓰인 부분이있는데,
    line 뒤에 ,가 붙는 이유를 모르겠습니다.

    • BlogIcon PinkWink 2019.10.22 19:46 신고

      단일 튜플이라고 합니다. 콤마가 없으면 그냥 하나의 변수인데, 반환값이 튜플일때 콤마를 사용해서 단일 튜플로 받게 됩니다.