addinedu

간장공장공장장: QR + ESP32 기반 스마트 분류 공장

간장공장공장장: QR + ESP32 기반 스마트 분류 공장

간장공장공장장은 컨베이어 위 QR 코드를 ESP32CAM으로 읽어 국내/해외 창고로 자동 분류하는 IoT + 백엔드 + 관리자 UI 통합 시스템입니다.

Python
FastAPI
MySQL
PyQt6
Arduino
ESP32
RFID
MQTT
Docker
TCP/UDP

Introduction

간장공장공장장은 컨베이어 벨트 위의 제품 박스에 부착된 QR 코드를 ESP32CAM으로 읽어, 주소를 기반으로 국내/해외 창고로 자동 분류하는 스마트 공장 시스템이다. 임베디드(ESP32 펌웨어), 백엔드(FastAPI), 관리자 UI(PyQt6), DB(MySQL)까지 한 시스템 안에 통합한 프로젝트.

soy factory demo

soy factory ui

System Architecture

구성요소기술 스택역할
SoyDBMySQL (Docker)제품·주소·출입·분류 등 전체 데이터 저장
SoyServer (중앙서버)Python, FastAPI, Alembic출입제어·분류·관리자 PC와 통신, DB 연동, 스키마 마이그레이션
SoyAdmin (관리자 PC)PyQt6모니터링·운영 UI, 작업자/공정 관리
작업자 등록키트Arduino Uno + RFIDRFID 카드 발급, 중앙서버와 Serial 통신
출입제어키트Arduino ESP32 + RFID출입 인증, 중앙서버와 TCP 통신
분류키트Arduino ESP32CAMQR 인식, 근접센서·서보·DC모터 제어, 중앙서버와 TCP/UDP 통신

Features

  • 자동 분류 공정: 컨베이어 → ESP32CAM(QR 인식) → 서버에서 주소 해석 → 서보모터로 국내/해외 분기
  • 3단계 공정 제어: 시작 / 일시정지 / 중지 분리. 일시정지는 DC 모터만 정지하고 카메라·DB 상태는 유지
  • RFID 출입제어: 등록된 작업자만 출입 허용, 카드 이벤트는 TCP로 중앙서버에 푸시
  • 작업자 카드 발급: 관리자 UI에서 신규 작업자에게 RFID 카드 등록
  • 공정 로그·모니터링: 작업 시작·종료·물품 인식·카운팅 로그를 DB에 저장하고 관리자 화면에서 조회

Implementation

1. ESP32 분류키트 — FSM 기반 상태 관리

분류 공정은 IDLE / RUNNING / SORTING / PAUSED 등의 상태를 가진다. ESP32 펌웨어에 FSM(Finite State Machine) 을 도입해 상태별 전이 규칙을 명시했다.

  • RUNNING 에서만 SORT_PAUSE 수신 → PAUSED 전이
  • PAUSED 에서만 SORT_RESUME 수신 → RUNNING 복귀
  • SORTING 중 일시정지 명령은 무시 (분류 동작 중 끊기지 않도록 보호)
  • 각 상태마다 RGB LED 색상 매핑 (PAUSED → 노랑) 으로 현장에서 상태를 즉시 인지 가능

2. QR 코드 인식률 개선

ESP32CAM 의 320x240 저해상도 + JPEG 압축 + 박스 회전 때문에 pyzbar.decode() 1회 호출만으로는 인식 실패가 잦았다. PC 쪽에서 다단계 디코딩 파이프라인을 도입했다.

1차: 원본 프레임 → pyzbar.decode()
2차: 90°, 180°, 270° 회전 → 각각 pyzbar.decode()
3차: 그레이스케일 + 적응적 이진화(adaptiveThreshold) → pyzbar.decode()
  • 성공 시 즉시 반환해 오버헤드 최소화
  • 최악의 경우 6회 decode 이지만 320x240 해상도라 충분히 빠름
  • 추가로 ESP32CAM 하드웨어 레벨에서 set_vflip 으로 영상 보정해 PC 측 cv2.flip 중복 처리 제거

3. SoyServer — MVC + 도메인 서비스 구조

FastAPI 서버는 단순 라우터 나열을 피하고 계층 분리 를 했다.

계층위치역할
Modelapp/models/, app/services/ORM 엔티티 + 도메인 로직. 프로토콜/전송 계층을 모름
Controllerapp/requests/TCP 요청 action + body 파싱 → app.services 호출
Viewapp/views/tcp_response.py응답 포맷 { type, id, ok, body, error } 으로 직렬화
전송app/pc_bridge.pyTCP 프레임 수신/송신, 세션 관리, _handle_request 로 라우팅
  • 도메인 예외(OrderNotFound, WorkerNotFound, WorkerCreateConflict 등)를 services 에서 던지고 controller 에서 응답으로 매핑
  • 인증 필요 액션(workers 관련)과 불필요 액션(auth, orders, processes)을 명확히 분리

4. 통신 프로토콜

  • HTTP 8000: REST API · health check · 문서
  • TCP 9001: SoyAdmin(PyQt) ↔ 서버. Worker CRUD, card_read 푸시
  • TCP: 출입제어키트 ↔ 서버 (RFID 인증 결과)
  • TCP/UDP: 분류키트 ↔ 서버 (TCP 분류 지시, UDP 카메라 스트림)
  • MQTT: ESP32 분류키트 상태 발행 (SORT_PAUSE, SORT_RESUME, PAUSED 등)

5. Docker 기반 통합 기동

docker compose up -d 한 번으로 MySQL + SoyServer + Adminer 가 동시에 기동되고, 서버 기동 시 Alembic 마이그레이션이 자동 적용되도록 했다. 시리얼 디바이스가 연결되지 않은 환경에서도 서버만 띄울 수 있도록 ./scripts/compose-up.sh 래퍼를 제공해 개발 편의성을 확보했다.

Tech Stack

  • 백엔드: Python 3.12, FastAPI, SQLAlchemy, Alembic
  • DB / 인프라: MySQL, Docker Compose, Adminer
  • 관리자 UI: PyQt6, Qt Designer
  • 펌웨어: Arduino, ESP32 / ESP32CAM, PlatformIO
  • 하드웨어: RFID 모듈, 근접센서, 서보모터, DC모터, ESP32CAM
  • 통신: TCP, UDP, MQTT, Serial
  • 이미지 처리: OpenCV, pyzbar
  • 패키지 관리: uv