안녕하세요.
실제로 연동하는 프로그램을 만들어 보려고 합니다.
이전 ModbusTCP내용과 PulseCount를 잘 조합하면 될 것으로 생각했습니다.
그런데 가상환경에서 RPi.GPIO의 add_event_detect() 함수를 사용하면 이벤트를 받아서 처리할 수가 없었습니다.
이전 내용을 참고하시면 pigpio 라이브러리 사용하는 방법을 다시 찾아서 확인하였습니다.
최종적로 ModbusTCP와 pigpio를 이용해서 작업을 마무리할 수 있었습니다.
1. 코드 구성 확인
소스코드를 보기 전게 간단하게 맥락을 설명하면 아래와 같습니다.
1) 필요한 라이브러리 및 모듈
pyModbusTCP: ModbusTCP 서버를 구현하기 위한 라이브러리
pigpio: GPIO 핀에서 센서 데이터를 안정적으로 읽어오기 위한 라이브러리
time: 시간 계산 및 흐름 제어
2) 유량 센서 설정
FLOW_SENSOR_PIN: 유량 센서가 연결된 라즈베리파이의 GPIO 핀 번호
PULSES_PER_LITER: 유량 센서가 1리터 유량당 발생시키는 펄스 수
3) 펄스 카운트와 유량 계산
count_pulse(): 센서에서 감지한 펄스를 카운트
get_flow_rate(): 펄스를 이용해 유량(L/min)을 계산
4) ModbusTCP 서버 구현
ModbusServer: ModbusTCP 서버 생성
서버는 유량 데이터를 Holding Register 주소 0번에 저장하며, 2자리 소수점은 정수 형태로 변환하여 저장
5) 메인 실행 흐름
Pigpio 초기화 및 센서 설정
ModbusTCP 서버 시작
루프에서 매초마다 유량을 계산하고 Modbus 레지스터에 값을 업데이트
2. ModbusTCP와 Flow 센서 연동 전체 코드
$ vim flow.py 해서 아래 코드 작성
#!/bin/python
from pyModbusTCP.server import ModbusServer
import time
import pigpio
# 센서 설정
FLOW_SENSOR_PIN = 17 # Sensor GPIO Pin number
PULSES_PER_LITER = 595 # 595 pulses generated in 1L valume
# 변수 초기화
pulse_count = 0
start_time = time.time()
# Create an instance of ModbusServer
server = ModbusServer("192.168.0.59", 1503, no_block=True)
# callback function of detected pulse
def count_pulse(gpio, level, tick):
global pulse_count
pulse_count += 1
# Flow calcuation function
def get_flow_rate():
global pulse_count, start_time
end_time = time.time()
elapsed_time = end_time - start_time
# flow calculation (L/min)
flow_rate = (pulse_count / PULSES_PER_LITER) * (60 / elapsed_time)
# count and time init
start_time = time.time()
pulse_count = 0
return flow_rate
if __name__ == "__main__":
# pigpio init
pi = pigpio.pi()
if not pi.connected:
print("The daemon is not running. Run the daemon.The daemon is not running. Run the daemon.: 'sudo pigpiod'")
exit(1)
# FLOW_SENSOR_PIN settings and registering callback functions
pi.set_mode(FLOW_SENSOR_PIN, pigpio.INPUT)
pi.set_pull_up_down(FLOW_SENSOR_PIN, pigpio.PUD_UP)
cb = pi.callback(FLOW_SENSOR_PIN, pigpio.FALLING_EDGE, count_pulse)
try:
print("Start server...")
server.start()
print("Server is online")
state = [0]
while True:
# call flow calculation function
flow_rate = get_flow_rate()
# Set value to Holding Register address 0
server.data_bank.set_holding_registers(0, [int(flow_rate * 100)]) # save as integer type(maintain 2 decimal places)
print(f"Flow Rate Updated: {flow_rate:.2f} L/min")
time.sleep(1)
except Exception as e:
print(f"Error occurred: {e}")
print("Shutdown server ...")
server.stop()
cb.cancel()
pi.stop()
print("Server is offline")
3. 실행 확인
pigpiod 데몬을 먼저 실행하고 이전에 설정한 가상환경을 실행한 후 소스를 실행합니다.
$ sudo pigpiod
$ source ~/virtualEnv/bin/activate
$ python flow.py
ModbusTCP에서도 정상적으로 연결되는지 확인하기 위해서 ModbusTCP Client(KiMons)를 사용해서 연결합니다.
포트는 이전에 사용하는 것으로 작동하고 1503으로 변경했습니다. Read Definition에서 Function은 03(Read Holding Registers)으로 설정한 후 읽으면 수치값이 변화하는 것을 알 수 있습니다.
4. 추가 진행해야 것들
이것으로 간단하게 유량측정값을 ModbusTCP를 이용해서 전달하는 것을 확인하였습니다.
그러나 위의 내용은 단순히 연동 작업이 가능한 것을 확인한 것이고, 실제로 사용하기 위해서는 코드 최적화 및 스레드를 사용한 Wirte 연동 및 예외처리... 자동실행을 위한 셀스크립트 등 작업을 해주어야 안정성 및 가치가 높아질 것입니다.
감사합니다.