티스토리 뷰

Intro

OS : MacOS, Ventura, v13.0.1

HW : Arduino UNO R3 board, DHT11 Sensor, LM35 Sensor

SW : Visual Studio Code, so-called vscode

python : 3.10.8

 

 

- Arduino 연결 부터 확인하려면 다음 포스트 참고

Arduino UNO DHT11 sensor 연결 및 모니터링

- Arduino Sensor DAQ 확인하려면 다음 포스트 참고

Arduino UNO DHT11 sensor DAQ

- Arduino Sensor multi DAQ 확인하려면 다음 포스트 참고

Arduino UNO DHT11/LM35 sensor multi DAQ

 

- 선행필요 : Arduino DAQ 관련 포스트 참고

(macOS)[python] Arduino DHT11/LM35 DAQ Monitoring with tkinter

 

 

Requirements

 - vscode

- vscode extension : Arduino

- python packages

pyserial

numpy

tkinter

matplotlib

pyinstaller

 

 

 

 

# pyinstaller 실행파일 만들기의 필수사항이 아님 : 3번 참고, 4번 항목 넘어가도 좋음

1. python 가상환경(venv: virtual environment)

zsh path 설정 : 가상환경 바로가기....

$ nano ~/.zshrc
....


alias venv='python3 -m venv'

## 참고: nano 환경 빠져나오기

key: control + 'o'

enter

key: control + 'x'

macOS: conrol... cmd가 아님....

 

zshrc 변경 적용

$ source ~/.zshrc

 

 

# project 개발 시 version 관리 용이함

가상환경 만들기 : venv 

가상환경 만들기 : venv 

$ venv persona_daq

$ source /bin/activate

(persona_daq) $ 

cmd+shift+p

 

## 참고 : 가상환경 활성/비활성/삭제

활성

$ source /yourProject/bin/activate

비활성

(yourProject)$ deactivate

삭제 : macOS finder 직접 삭제 가능

$ rm -rf [yourProject]

-> 안되면.... sudo rm -rf [yourProject]

 

 

2. vscode : 가상환경 진입

project 열기 : persona_daq

python: select interpreter

venv 상태 확인

 

 

3. python Code : 이전 포스트 code 일부 수정

persona_daq.py
import os
import serial
import numpy as np
import time
import tkinter as tk
import matplotlib.pyplot as plt
import matplotlib.animation as animation


## initial params.
global ard, sw, y_sum
sw = 0
y_sum = np.empty((0,3), dtype=float)
save_data = np.empty((0,5))

## initial tkinter graph
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
ax2 = ax1.twinx()
ax1.set_xlim([0,10])
ax1.set_ylim([0,100])
ax2.set_ylim([0,70])


## daq_ard plot function : Data AcQuisition from Arduino Board
def daq_ard(i):
	global sw, y_sum, save_data
	if(sw == 1):
		td = time.strftime('%Y-%m-%d', time.localtime())
		tt = time.strftime('%H:%M:%S', time.localtime())
		datas_raw = ard.readline()
		## ard.decode() : readline을 decoding
		datas = datas_raw.decode()[:len(datas_raw)-2]
		print('Decoded data:{}, type:{}:'.format(datas,type(datas)))
		T1S1 = float(datas[5:10])
		T2S2 = float(datas[10:15])
		H1S1 = float(datas[0:5])
		y_new = np.array([[T1S1,T2S2,H1S1]])
		print(y_new[0],type(y_new[0]))
		print('y_new(float):{}, type:{}'.format(y_new,type(y_new)))
		y_sum = np.append(y_sum,y_new,axis=0)
		print('DAQ count: {}'.format(len(y_sum)))
		print('Data Stack: T1S1  T2S2  HumS1\n{}'.format(y_sum))
		
		## axes clear/limit
		ax1.clear()
		ax2.clear()
		# ax1.set_xlim([int(len(y_sum)-10),int(len(y_sum))])
		ax1.set_xlim([int(0),int(len(y_sum)+2)])
		plt.xticks(range(0,len(y_sum),1))
		ax1.set_ylim([0.0,100.0])
		ax2.set_ylim([0.0,70.0])
		
		## plot 3-datas from sensor 2EA, 
		ax1.plot([i for i in range(int(len(y_sum)))],y_sum[:,0],'ro-',label='Temp.1')
		ax1.plot([i for i in range(int(len(y_sum)))],y_sum[:,1],'go-',label='Temp.2')
		ax2.plot([i for i in range(int(len(y_sum)))],y_sum[:,2],'b*--',label='Humidity')
		
		## title/label
		ax1.set_title('Temp. vs Time')
		ax1.set(xlabel='Time[sec]',ylabel='Temp.[oC]')
		
		## legend/grid
		ax1.legend(loc="upper left")
		ax2.legend(loc="upper right")
		plt.grid()

		databysave = np.array([[td,tt,y_new[0][0],y_new[0][1],y_new[0][2]]])
		save_data = np.append(save_data,databysave,axis=0)
		
	else:
		print("Please Push the START button")


#### tkinter loop
root = tk.Tk()
root_title = 'Temperature DAQ System'
root.title(root_title)
# win_size : width x height + x_position + y_position
root_size = '200x100+650+20'
root.geometry(root_size)
## .resizable : move (vertical, horizontal) True or False
root.resizable(False, False)

## start btn : Arduino set-up
def start():
	global ard, sw
	## arduino board set-up
	serial_port = '/dev/tty.usbmodem141101'
	serial_baudrate = 9600
	ard = serial.Serial(serial_port,serial_baudrate)
	for tt in range(5,0,-1):
		test_raw = ard.readline()
		test = test_raw.decode()[:len(test_raw)-2]
		print("starting...#{} | testing....:{} ".format(tt,test))
		time.sleep(1)
	print("START")
	sw = 1
	

## stop btn
def save():
	print("Start Save....")
	global save_data
	spath = './save_daq'
	sname = 'data_save.csv'

	if not os.path.exists(spath):
		os.mkdir(spath)

	csv_rows = ["{},{},{},{},{}".format(i,j,k,l,m) for i,j,k,l,m in save_data]
	csv_text = "\n".join(csv_rows)
	with open(os.path.join(spath,sname), 'w') as cf:
		cf.write(csv_text)
	cf.close()
	for tt in range(3,0,-1):
		print("saving....#{} ".format(tt))
		time.sleep(1)
	print("save_path:{}{}".format(os.getcwd(),spath[1:]))
	print("Complete Save!!")

## stop btn
def stop():
	global ard, sw
	ard = None
	sw = 0
	print("stop")
	ax1.clear()
	ax2.clear()
	plt.close()
	root.destroy()

btn_start = tk.Button(root,text='START',overrelief='groove',fg='black',width=10,command=start,repeatdelay=1000,repeatinterval=100)
btn_start.pack()
btn_save = tk.Button(root,text='SAVE',overrelief='groove',fg='blue',width=10,command=save,repeatdelay=1000,repeatinterval=100)
btn_save.pack()
btn_stop = tk.Button(root,text='STOP',overrelief='groove',fg='red',width=10,command=stop,repeatdelay=1000,repeatinterval=100)
btn_stop.pack()

anim = animation.FuncAnimation(fig,daq_ard,interval=1000)

plt.show()

root.mainloop()
#### tkinter loop

 

python 파일 실행.... 누르면 당연하지만 실행이 안된다.

이전 포스트에서 작성 시 설치했던 package는 가상환경이 아닌 macOS 전역 공간에 설치되었기 때문

실행하면서 에러가 발생한 line의 필요한 package를 설치한다. 물론 가상환경 활성상태 vscode 터미널이나, iterm에서....

 

 

package(or module or library)  install

(persona_daq)$ pip3 install --upgrade pip

(persona_daq)$ pip3 install pyserial

(persona_daq)$ pip3 install numpy

(persona_daq)$ pip3 install matplotlib

 

 

가상환경에 설치된 Package 확인

(persona_daq)$ pip3 list

Package         Version
--------------- -------
contourpy       1.0.6
cycler          0.11.0
fonttools       4.38.0
kiwisolver      1.4.4
matplotlib      3.6.2
numpy           1.23.4
packaging       21.3
Pillow          9.3.0
pip             22.3.1
pyparsing       3.0.9
pyserial        3.5
python-dateutil 2.8.2
setuptools      65.4.1
six             1.16.0

 

 

requirements.txt 생성

(persona_daq)$ pip3 freeze > requirements.txt

## 참고 배포 시 설치 방법 : pip3 install -r requirements.txt

(persona_daq)$ cat requirements.txt

contourpy==1.0.6
cycler==0.11.0
fonttools==4.38.0
kiwisolver==1.4.4
matplotlib==3.6.2
numpy==1.23.4
packaging==21.3
Pillow==9.3.0
pyparsing==3.0.9
pyserial==3.5
python-dateutil==2.8.2
six==1.16.0

 

 

README.md : options... 굳이 필요는 없으나 실행파일 설명

아두이노 센서 2개 데이터를 수집하는 실행파일

1. python3.10.8
2. 필요한 python package : requirements.txt 확인
3. Arduino 연결 방법 및 python code 제작 관련 문서 사이트
   https://jinozblog.tistory.com/190
4. arduino file : ard_tkinter_dht11_lm35.ino
5. dist/persona_daq/src
    - ard_tkinter_dht11_lm35.ino
    - requirements.txt
    - README.md

 

 

 

4. 실행파일 만들기 : pyinstaller 

pyinstaller 설치

(persona_daq)$ pip3 install pyinstaller

 

실행파일 생성

src 폴더에 필요한 파일 모으기

- Arduino.ino : ard_tkinter_dht11_lm35.ino : 링크

- requirements.txt

- README.md

 

(persona_daq)$ pyinstaller --add-data "src/*:src" persona_daq.py

2개의 폴더와 1개의 파일이 생성

build

dist

persona_daq.spec

 

패포판 : dist폴더에 생성

## 참고. add-data path:  dist/persona_daq/src

 

 

실행파일 확인

exec, 즉 실행파일 생성

dist/persona_daq/persona_daq

>> 실행 결과 : terminal, figure, tkinter 3종 window 생성

 

 

 

## 참고: onefile 실행파일 생성 / terminal 없애기

onefile...

(persona_daq)$ pyinstaller --onefile persona_daq.py

dist 폴더에 파일이 persona_daq 1개만 존재

 

terminal(console) window 실행이 안되게....

(persona_daq)$ pyinstaller -w persona_daq.py

 

 

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함