반응형

안녕하세요. 아두이노 MQ Series PPM으로 변환하기 번외 편입니다. 

 

저번 글은 회로도를 보았고, 오늘은 파이썬으로 PPM으로 변환하도록 하겠습니다.

 

파이썬으로 굳이 사용한 이유는 급하게 실험하느라, 센서 값을 PPM으로 변환하지 않고 그대로 CSV파일 형식으로 받았기 때문에 파이썬으로 데이터를 전처리해야만 했습니다.

 

import csv
import numpy as np
import math
import matplotlib.pyplot as plt

"""
PPM 
VCC = 3.3V
RL = 10k

VL = VCC*(RL/(RS+RL)
RS = (RL*VCC)/VL-RL

PPM = a * ratio * b
"""

vcc = 3.3
rl = 10
mq3, mq4, mq6, mq7, mq8, mg811 = 7, 8, 9, 10, 11, 12


#  Calculate Rs 
def rs_cal(vl):
    return ((vcc * rl) / vl) - rl


# Calculate Ro
def ro_cal(rs, num, clean_air_ppm):
    ro_tmp = 0
    for i in range(num):
        ro_tmp += rs[i] / clean_air_ppm
    return ro_tmp/num


# Calculate ratio 
def ratio_cal(rs_, ro_):
    return rs_/ro_


# Calculate PPM 
def ppm_cal(ratio, a, b):
    return a * pow(ratio, b)

# Calculate logscale PPM
def ppm_log_cal(ratio, a, b):
    return (math.log10(ratio)-b)/a


def co2_cal(adc_v):
    return pow(10, ((adc_v / 8.5) - 0.220) / (0.020 / (2.602 - 3)) + 2.602)


constant = {"mq3": ['Alcohol', "mq3", 0.3934, -1.504],
            "mq4": ['CH4', "mq4", 1012.7, -2.786],
            "mq6": ['LPG', "mq6", 1009.2, -2.35],
            "mq7": ['CO', "mq7", 99.042, -1.518],
            "mq8": ['H2', "mq8", 976.97, -0.688]}


file_name_1 = '2020923_105132.csv'
file_name_2 = '2020923_113418.csv'
file_name_3 = '2020923_125810.csv'

header = ['boot_ms[ms]',
          'latitude[degE7]', 'longitude[degE7]', 'relative altitude[mm]',
          'local position x[m]', 'local position y[m]', 'local position z[m]',
          'mq3', 'mq4', 'mq6', 'mq7', 'mq8', 'mq811',
          'PM1.0', 'PM2.5', 'PM10.0', 'ozone', 'gamma']


csv_1 = np.loadtxt(file_name_1, delimiter=",")
# file = np.vstack([header, csv_1])

adc_v_list = []
rs_list = []
ratio_list = []
ppm_list = []

tmp = []

for i in range(len(csv_1)):
    adc_v_list.append(csv_1[i][mq4])

for i in range(len(csv_1)):
    rs_list.append(rs_cal(csv_1[i][mq4]))

ro = ro_cal(rs=rs_list, num=10, clean_air_ppm=4.4)

for i in range(len(csv_1)):
    ratio_list.append(ratio_cal(rs_list[i], ro))

for i in range(len(csv_1)):
    ppm_list.append(ppm_cal(ratio_list[i], constant['mq4'][2], constant['mq4'][3]))

time = []

for i in range(len(csv_1)):
    time.append((csv_1[i][0]-csv_1[0][0])/1000/60)

print("time :", time)
print("adc_v :", adc_v_list)
print("ro :", ro)
print("rs :", rs_list)
print("ratio : ", ratio_list)
print("ppm :", ppm_list)
print("clean air :", 1012.7 * pow(4.4, -2.786))

plt.plot(time, [300 for _ in range(len(csv_1))], color='red')
# plt.plot(time, [10000 for _ in range(len(csv_1))], color='red')
plt.plot(time, ppm_list, color='green')
plt.xlabel('[Minute]')
plt.ylabel('[PPM]')
plt.title("MQ4 - CH4( 300~10000ppm )")
plt.show()

 

위 소스코드 같은 경우는 프로젝트에서 중요하다고 생각한 부분만 가져왔습니다. 

 

아래는 PPM으로 변환할 때 필요한 함수입니다.

#  Calculate Rs 
def rs_cal(vl):
    return ((vcc * rl) / vl) - rl


# Calculate Ro
def ro_cal(rs, num, clean_air_ppm):
    ro_tmp = 0
    for i in range(num):
        ro_tmp += rs[i] / clean_air_ppm
    return ro_tmp/num


# Calculate ratio 
def ratio_cal(rs_, ro_):
    return rs_/ro_


# Calculate PPM 
def ppm_cal(ratio, a, b):
    return a * pow(ratio, b)

# Calculate logscale PPM
def ppm_log_cal(ratio, a, b):
    return (math.log10(ratio)-b)/a

 

그리고 기억은 잘나지 않지만, CO2 센서는 위 공식 말고 다른 식을 사용합니다. 

# Calculate CO2 PPM
def co2_cal(adc_v):
    return pow(10, ((adc_v / 8.5) - 0.220) / (0.020 / (2.602 - 3)) + 2.602)

 

1편

coding-yoon.tistory.com/98

 

[아두이노] MQ 시리즈 공기질 센서 PPM으로 변환하기! (1) Feat. MQ2, MQ3, MQ4, MQ5, MQ6, MQ7, MQ8, MQ9, MG-811

안녕하세요. 약 두 달만에 글을 씁니다. 공모전과 기사 시험의 지옥을 뒤로 잠시 여유가 생겨 시간을 냅니다. 오늘은 MQ 시리즈에서 공기질 센서를 PPM으로 변환하는 방법에 대해 글을 쓰겠습니

coding-yoon.tistory.com

 

2편

coding-yoon.tistory.com/121

 

[아두이노] MQ 시리즈 공기질 센서 PPM으로 변환하기! (2) 회로도 (Schematic)

안녕하세요. MQ시리즈 두 번째 글을 작성합니다. 확실히 글은 바로 바로 작성하는 것이 중요한 것 같습니다. 글을 쓰려고 보니 기억이 안 나서 다시 새로 공부했습니다. 저번 글은 아두이노 라이

coding-yoon.tistory.com

 

728x90
반응형
반응형

안녕하세요.

 

오늘은 PyQt5에 matplotlib를 연동하는 방법에 대해 이야기하겠습니다.

 

 

제가 이번에 만든 필터를 구현하면서 애먹었던 부분 중 하나였던게

 

pyqt5에 plt를 연동시키는 것이였습니다.

 

결국 답이 레퍼런스 찾아보거나, stackoverflow를 통해 방법을 알아냈습니다.

 

우선 pyqt5에 matplotlib를 연동시키는 방법을 설명하겠습니다. 

 

 

 

 

1. pyqt5에 plt 연동

 

 

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas

 

 

우선 import 부분에 위에 문구를 추가해줍니다.

 


from matplotlib import pyplot as plt



self.fig = plt.figure(figsize=[4, 4])



a = plt.subplot(2, 1, 1)
a1 = plt.subplot(2, 1, 2)





 

plot이 두개 담겨있는 fig가 변수로 저장이 되어있겠죠?

 

사용법은 간단합니다.

 

위에 import 해준 라이브러리를 사용하기 위해 fig를 FigureCanvas에 담아주면 됩니다. 

 


from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import pyplot as plt



self.fig = plt.figure(figsize=[4, 4])



a = plt.subplot(2, 1, 1)
a1 = plt.subplot(2, 1, 2)

self.canvas = FigureCanvas(self.fig)



 

정말 간단하죠?

 

 

 

2. pyqt5에 toolbar 연동

 

툴바

위의 사진들 많이 보셨죠?

 

self.fig.show() 하면 보이는 툴바입니다.

 

툴바는 plot을 만들어서 분석하기 위해 확대하교 움직이기 위해 사용합니다.

 

사용방법은 FigureCanvas랑 비슷합니다.

 




from matplotlib import pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar



self.fig = plt.figure(figsize=[4, 4])



a = plt.subplot(2, 1, 1)
a1 = plt.subplot(2, 1, 2)

self.canvas = FigureCanvas(self.fig)
self.toolbar = NavigationToolbar(self.canvas, self)


 

 

네. 비슷하기는 하지만 인자가 하나 더 들어가있죠?

 

 

첫번 째 인자로 우리가 방금 연동시킨 FigureCanvas가 들어가네요?

 

두번 째 인자로는 부모 인자를 넣으라 하는군요. 부모인자라 하면은 뭘까요?

 

우리들은 pyqt5를 사용하기 전에 우리들은 QWidget을 상속받아 사용합니다.

 

제 프로그램을 예시로

 

이런식으로 QWidget을 상속받고, self로 초기화 시킵니다. 

 

간단히 말해 parent 자리에 self를 넣어주면 됩니다.

 

 

 

3. Layout에 붙이기

 

2번까지 끝나셨으면 우리들에게는 두 개의 widget이 존재합니다.

 

self.canvas

self.toolbar

 

이제부터는 PyQt5의 기본 레이아웃 문제로 변하게 됩니다.

 

우선 저 같은 경우는 일단 Designer는 사용하지 않습니다. 

 

exe를 만들기 어려울뿐더러 하나 하나 코딩 한 줄 넣는게 저에겐 덜 헷갈려서 코딩으로 적겠습니다.

 

위에 그림처럼 위젯을 붙이기 위해서는 

 

수직으로 배치하는 QVBoxLayout (vertical)

 

lay = QVBoxLayout()

lay.addWidget(self.toolbar)
lay.addWidget(self.canvas)

 

짠!

 

만약 툴바를 아래로 내리고 싶으시면

 

lay = QVBoxLayout()

lay.addWidget(self.canvas)

lay.addWidget(self.toolbar)

짠!

 

두 위젯이 lay라는 레이아웃에 담겨 있습니다. 

 

이제 show를 해줍시다.

 

self.setLayout(lay)

 




from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import pyplot as plt
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar



self.fig = plt.figure(figsize=[4, 4])



a = plt.subplot(2, 1, 1)
a1 = plt.subplot(2, 1, 2)

self.canvas = FigureCanvas(self.fig)
self.toolbar = NavigationToolbar(self.canvas, self)

lay = QVBoxLayout()
lay.addWidget(self.canvas)
lay.addWidget(self.toolbar)

self.setLayout(lay)


 

 

이런식으로 pyqt5에 matplot 연동시키시면 됩니다.

 

728x90
반응형
반응형

안녕하세요. 

 

몇 일동안 글을 못올렸습니다. 

 

그 이유가 제가 이번에 하이패스필터, 로우패스필터, 밴드패스 필터를 구현하였습니다.

 

파이썬응용에 글에 썻던 scipy는 사용하지 않았습니다.

 

공식을 보고 하나 하나 구현하였습니다. 

 

하지만 문제가 하나 발생했습니다. 어휴... 티스토리 동영상 업로드가 안되네요...

 

열심히 찍었는데... 안올라가더라구요 ㅠ. HTML을 손보면 된다는데... 힘쓰는게 너무 싫어서... 그냥 스크린샷으로 하겠습니다.

 

처음 시작 부분입니다.

 

 

메뉴바에서 파일선택부분입니다.

 

 

만약 파일을 선택하지 않으면 필터가 잠겨있습니다.
파일여는 부분입니다.

 

아래 상태창에 경로 뜨는거 보이시죵 ㅎ... 왠지 멋잇어보여서
고역패스필터가 선택되어있네용
이거는 로우패스필터네용

 

 

이번엔 차수가 2이네요

 

 

적용을 하니 save가 열리네요

 

적용된 파일이 저장되어있네요

어후... 막상 스크린샷을 찍어서 올리긴 했는데

 

너무 난잡하고 뭘 설명하는지 모르겠네요...

 

내일 다시 한번 동영상 올리도록하겠습니다. 

 

제가 먼가 pyqt5, 필터, librosa 함수 여러가지를 공부했다는것을 뿜뿜 하고싶은데 블로그에서 막혀버리네용

 

일주일동안 열심히 만들었는데... ㅠ

 

728x90
반응형

+ Recent posts