상위 문서: 제어 고도화·AI 도입 통합안 v1 · 근거 문서: 15분 잔여 허용량 3층 구조 v3
결론부터: 지금 피크제어는 1초마다 순간 kW ÷ 적용전력으로 단계를 정하고, 제어 간격마다 한 대씩 걸고 풉니다. 평시에는 등록 설비 전체에 정상가동률을 걸며, AI를 켜면 Chronos가 다음 15분 블록 평균을 예측해 이 정상가동률을 바꿉니다. 여력이 충분하면 대부분 막지만(3층 문서 32조건 시뮬레이션. 막을 수 있는 양은 설비 유형에 따라 크게 다름), 15분 평균이라는 목표를 직접 보지 않아 필요 없이 누르고, 기록이 부족해 얼마나 줄었는지 모릅니다. 개선은 기록(0) → 15분 예산 계산과 P_end+(1) → 감축표와 ΔP 동시 제어(2) → 남은 구간 예측과 할당 최적화(3) 순서입니다. 이번 코드 확인에서 기존 문서에 없던 점 두 가지(제어 로그에 걸린 레벨 행과 전후 kW가 남지 않음, AI 예측 입력에 진행 중 블록 포함)를 새로 찾았습니다. PLC 동작을 확인하면서 가동률은 전력 비율이라는 점(정토크 설비는 걸어도 덜 줄어듦)도 정리했습니다.
표시확인 10/12 코드로 확인가정 추정·미확인신규 이번에 새로 찾은 문제
0
한눈에 보기
단계
바꾸는 것
AI
넘어가는 조건
0 기록
제어 로그에 레벨 행·변경 전후 kW 추가, 별도 15분 누적기, 총전력 10초 보관
없음
2주 누락 없음
1 기본값
15분 예산 계산(층 1), 그림자 2주 → 레벨 판정을 P_end로, 해제는 P_end+ 확인, 정상가동률과 피크 값 비교 규칙, 구간 진행 화면
없음
놓친 구간 ≤ 현재 방식
2 계수
설비 감축표 자동 생성, ΔP만큼 동시 제어, 피크 위험 시간표, 회피 피크 집계
회귀·통계
감축 예측 오차 중앙값 15% 이내
3 예측·최적화
남은 구간 예측(Chronos·LightGBM 바꿔 쓰기), 설비·가동률 자동 결정, AI 정상가동률 경로 정리
지도학습·최적화
그림자에서 예측 오차 20% 이상 개선
4 선택
구간 전체를 보는 강화학습(시뮬레이터 안에서만)
강화학습
3단계로 안 될 때
1
지금 피크제어가 하는 일
1-1
매초 흐름
그림 1. 긴급 피크(주의·경계·위기)는 레벨에 따라 설비를 한 대씩 걸고, 평시에는 등록 설비 전체에 정상가동률을 겁니다. AI는 정상가동률만 바꿉니다.
1-2
코드로 확인한 동작
항목
동작
위치
레벨 판정
순간 totalkw ÷ cost_applykw × 100을 [위기;경계;주의] %와 비교(≥). 히스테리시스·유지 시간 없음. 100% 이상이면 알람(진짜 알람은 10초 간격)
smartControl.getNowPeakLevel 확인
제어 간격
auto_control_param.value(초). 제어 중인 설비가 0대면 첫 제어는 대기 없이 즉시, 이후에는 간격마다 한 번
runControlUnit
한 번에 바꾸는 수
해제 후보가 있으면 해제 1대만, 없으면 제어 1대만. 해제가 항상 먼저
runControlUnit
해제 후보
등록 레벨 > 현재 레벨인 제어 중 행, 순번 오름차순
AutoControlUnits.get_release_candidates
제어 후보
등록 레벨 ≤ 현재 레벨, 적용 켬, 물리 전원 켬, 기동 유예 아님. 레벨 내림차순 → 순번 오름차순
get_control_candidates
레벨 행 누적
경계로 올라가도 주의 행은 풀리지 않음. 설비에 여러 행이 걸리면 가장 높은 레벨 행의 값을 씀
get_active_by_unit_nums
기동 유예
꺼짐 → 켜짐 직후 운전 스케줄러 간격(초)만큼 제어 대상 선정과 PLC 적용 모두 제외. 기본 20초
get_startup_control_grace_sec
PLC 적용
긴급: 부하적응 OFF 확인 후 D1010 = 행 가동률 × 10, 그다음 M1006 ON. 평시: 등록 설비면 D1010 = 정상가동률 × 10. PLC가 가동률을 Hz로 바꿔 걸고 그 값을 D1020에 씀(1-4). 서버는 쓰기 성공만 확인하고, 매초 읽는 D1020을 반영 확인에는 쓰지 않음
emsPlcClient.runControl
우선순위
한 설비를 여러 정책에 동시에 등록할 수 있고, 매초 기동 유예 > 절전 > 긴급 피크 > 부하적응·공정제어 > 평시 정상가동률 순서로 하나만 적용. 예: 피크와 부하적응에 함께 등록된 설비는 긴급 피크가 걸린 동안만 피크 가동률, 풀리면 부하적응 Hz
runControl 분기 순서
15분 누적
정각 기준 15분 구간, 샘플 합 ÷ 샘플 수. 구간 행을 매초 덮어씀. 재시작하면 0부터
datareproc.avrgPeak15minKwProc
총전력 보관
매초 저장 후 1분마다 최대값만 남기고 삭제
RealtimeDBManager.save_sec_data
제어 기록
상태가 바뀔 때 auto_control_units_log에 적용전력·순간 kW·레벨·설비·가동률 기록
AutoControlUnitsLog.insert
1-3
AI 정상가동률 경로 (aiControlProc2)
제어 간격마다 avrg_kw_peak_15min_data 최근 7일(최대 672블록)을 읽어 Chronos-2로 다음 15분 블록 평균의 0.9 분위수를 예측합니다 확인.
예측 비율이 주의 미만이면 100%, 주의~경계면 "주의 등록 설비 가동률 최댓값 ~ 100%" 사이를, 경계~위기면 "경계 최댓값 ~ 주의 최댓값" 사이를 선형 보간(버림), 위기 이상이면 위기 최댓값을 그대로 씁니다.
결과를 마스터 행 aicontrol_value에 쓰고, dataserver는 하트비트가 60초 안이면 그 값을 정상가동률로 씁니다. 끊기면 AI를 자동으로 끄고 알람과 사용자 제어 기록을 남깁니다.
참고: 운영 설명자료(AI 제어 설명자료)에는 LLM(Qwen3-8B) 방식으로 적혀 있지만, 10/12 코드의 실행 스크립트(start.sh)가 띄우는 것은 Chronos-2 방식(aiControlProc2)입니다.
1-4
PLC가 가동률을 적용하는 방식
D1010의 가동률은 전력 비율입니다. PLC는 부하적응이 꺼져 있으면 60Hz(정상 운전)를 100%로 놓고, 팬 공식(전력 ∝ Hz³)을 거꾸로 풀어 Hz = 60 × (가동률)1/3로 낮춘 뒤 그 값을 인버터에 걸고 D1020에 씁니다. 지금 Hz가 이미 그보다 낮으면 건드리지 않습니다(상한으로만 작동) 확인.
가동률
PLC가 거는 Hz
팬·펌프 전력
정토크 설비 전력(압축기 등)
90%
57.9Hz
약 90%
약 96.5%
80%
55.7Hz
약 80%
약 92.8%
70%
53.3Hz
약 70%
약 88.8%
60%
50.6Hz
약 60%
약 84.3%
50%
47.6Hz
약 50%
약 79.4%
팬·펌프는 설정한 가동률만큼 전력이 줄지만, 전력이 Hz에 비례하는 정토크 설비는 80%를 걸어도 7% 정도만 줄어듭니다. 레벨 행을 짤 때 이 차이를 감안해야 합니다. 피크와 부하적응을 함께 등록한 설비는 긴급 피크 때 부하적응이 꺼지고 60Hz 기준 가동률이 걸리므로, 피크 행 가동률이 평소 부하적응 운전보다 낮은 출력이 되게 잡아 두어야 합니다(예: 평소 45Hz면 가동률 42% 아래). 설정할 때 고려할 점입니다. PLC 동작은 실장비 시험을 거쳐 만든 사내 PLC 시뮬레이터(DemoSimulatorPLC) 기준입니다.
2
문제점
#
문제
영향
근거
P1
요금은 15분 평균인데 판정은 순간값
늦게 들어온 부하처럼 넘지 않을 구간에서도 누름(불필요 제어). 앞에서 많이 쓴 구간은 순간값이 낮아도 넘을 수 있음
3층 ·
P2
걸고 푸는 기준이 같은 임계선, 히스테리시스 없음
제어 효과가 순간값을 내리면 바로 해제 → 다시 오름(흔들림). 간격이 완충 역할만 함
3층
P3
간격마다 한 대씩
간격 61초 현장에서 4대를 걸면 마지막 설비는 3분 뒤. 늦게 걸수록 이번 구간 기여가 작음
3층
P4
실제 감축량을 재지 않음
가동률이 전력 비율이라 설비 유형을 알면 예상 감축은 계산할 수 있음(1-4). 하지만 걸고 나서 실제로 몇 kW 줄었는지, 반영까지 몇 초인지는 기록하지 않아 제어 여력 C가 추정값에 머묾. D1020으로 적용 Hz를 읽을 수 있는데도 반영 확인에 쓰지 않음
runControl 확인
P5
15분 누적이 샘플 평균이고 재시작 시 소실
통신이 빠진 초만큼 덜 쓴 것으로 계산(제어가 덜 걸리는 쪽으로 틀림). main 통신이 끊기면 총전력 0이 섞임
3층
P6
정상가동률과 피크 행이 같은 D1010을 씀
정상가동률이 피크 행 값보다 낮을 때 피크가 걸리면 가동률이 오히려 오름(예: 65 → 74). AI 보간 결과도 이런 값을 낼 수 있음
3층
P7
제어 로그로 효과를 복원할 수 없음
로그 칸은 웹 화면 관례대로 쓰임(auto_control_units_num = 설비 번호, used = 1 제어/0 해제, now_peaklevel = 그때의 현재 레벨). 그래서 어느 레벨 행(행 번호·행 레벨·행 가동률)이 걸렸는지와 변경 전후 설비 kW가 남지 않고, 칸 이름과 실제 의미도 달라 분석 때 혼동됨
smartControl._commit_changes, webserver report/alarmLog 신규
P8
AI 예측 입력에 진행 중 블록이 섞임
avrg_kw_peak_15min_data의 현재 구간 행은 매초 부분 평균으로 덮어써지는데, 예측 입력 7일치 마지막 점으로 그대로 들어감. 구간 초반의 부분 평균이 "완료된 블록"처럼 취급되고, 예측 대상(다음 블록)과 제어가 적용되는 구간(지금 블록)도 어긋남
peakControl/getDataSet.get_peak15min_history 신규
P9
한전 계량 15분 구간과 서버 구간 정렬 미확인
서버 시계 기준 구간이 한전과 어긋나면 예산 계산 전체가 밀림
3층 ④
3층 문서의 시뮬레이션 결론은 그대로입니다. 여력이 충분한 구성에서는 현재 방식도 15분 피크를 대부분 막고(여력 안 초과 1,200구간 중 최대 2건), 문제는 불필요 제어와 측정 불가입니다. 11/6에 가동률을 전력 비율로 바꿔 다시 돌려도 방식 비교 결론(P_end+가 초과는 비슷하고 불필요 제어를 줄임)은 같았고, 정토크 위주 현장은 같은 레벨 행으로 막을 수 있는 양이 절반 수준으로 줄었습니다(3층 ).
3
모듈별 개선 설계
통합안의 M1~M7 구조에 맞춰, 피크제어에서 각 모듈이 무엇이고 단계마다 어떻게 바뀌는지 적었습니다.
M1
수집: 제어 이벤트 로그와 누적기
0단계
기존 칸은 그대로
웹 제어 이력 화면(report/alarmLog)이 지금 관례(auto_control_units_num = 설비 번호, used = 제어/해제)로 읽으므로 기존 칸의 의미는 바꾸지 않음. 비어 있는 control_value에 걸린 행 번호·행 레벨을 넣거나, 새 칸을 추가. P7 해결
로그 확장
같은 행에 변경 직전 10초 평균 설비 kW·총전력, 30·60초 뒤 설비 kW·총전력과 D1020 적용 Hz(반영 확인), 판정 방식(순간값/P_end), 입력 출처(룰/AI)를 추가. 30·60초 뒤 값은 다음 루프들에서 채움
별도 15분 누적기
기존 화면·테이블은 그대로 두고, 시간 가중(누적kWh = 평균 × 경과초 ÷ 3600), 재시작 복구(안 되면 빠진 시간을 목표치로 쓴 것으로 보수적으로 채움), main 통신 끊긴 초 처리(직전 값 유지 + 무효 표시)를 하는 누적기를 따로 둠. P5 해결
총전력 보관
학습용으로 10초 평균을 별도 보관(지금은 1분 최대값만 남음)
코드 위치(예상)
smartControl.runControlUnit, datareproc(새 누적기 클래스), dataserver 메인 루프 가정
M2
목표: 15분 예산
1단계 · 계산식
값
E_B = 목표kW × 0.25h, E_r = E_B − 지금까지 쓴 kWh, P_allow = E_r ÷ 남은 시간(h)
목표
cost_applykw를 하드코딩하지 않고 입력값으로 받음(나중에 하드·소프트 2단 목표선). 한전 구간 정렬 전까지 × 0.97 여유
저장
dataserver 안에서 매초 한 번 계산해 피크제어는 바로 쓰고, 공유 테이블 한 행에 덮어써서 AI·스케줄러·화면이 읽음 3층
M3
예측: 남은 구간 평균
1단계 계산 → 3단계 AI
1단계
P_예측 = 최근 1~3분 평균. 창은 구간 경계에서 끊지 않음(이전 구간 데이터 이어 씀)
3단계
「AI 도입 지도」 남은 구간 예측기. 진행 중 구간의 경과 시간과 누적량을 입력에 명시하고 이번 구간 종료 평균을 예측. Chronos-2로 시작하고 데이터가 쌓이면 LightGBM을 학습시켜 최근 성적이 좋은 쪽으로 바꿔 씀(섞지 않음, 3차 자문)
AI 경로 정리
지금의 "다음 블록 0.9 분위" 예측은 P8 때문에 입력에서 진행 중 블록 행을 빼거나, 부분 평균을 경과 시간과 함께 따로 넣도록 바꿈. 최종적으로는 01로 통합
켜는 기준
그림자 2주, 구간 종료 평균 예측 오차가 최근 평균 방식보다 20% 이상 작을 때
남는 질문
초반 기동 스파이크를 "계속될 부하"로 읽는 문제(3층 )를 예측 모델이 실제로 구분하는지. 교수님께 드린 역질문
M4
감축량: P_end, ΔP, 제어 여력
1단계 · 계산식
값
P_end = (쓴 kWh + P_예측 × 남은 시간) ÷ 0.25h, ΔP = P_예측 − P_allow, C = 후보 설비들의 (현재 kW − 최대 제한 시 kW) 합
C의 전제
설비별 "제한하면 몇 kW 줄어드는가"는 2단계 감축표가 생겨야 정확. 그전에는 1-4 표로 계산. 가동률이 전력 비율이므로 60Hz로 돌 때의 kW를 기준으로 팬·펌프는 kW × (1 − 가동률), 정토크 설비는 kW × (1 − 가동률1/3). 설비 유형을 모르면 두 값 사이 범위로 표시
쓰는 곳
레벨 판정(1단계), 동시 제어 대수(2단계), 화면의 "방어 가능/불가"
M5
할당: 어느 설비를 얼마나
1 → 2 → 3단계
단계
방식
1
지금 그대로(레벨 행·순번·간격당 한 대). 바뀌는 것은 레벨을 정하는 분자(순간 kW → P_end)뿐
2
ΔP만큼 한 번에: 순번대로 감축표의 예상 감축을 더해 ΔP × 1.2에 닿으면 멈추고 한꺼번에 걸기 3층 ·
3
「AI 도입 지도」 : 사람이 짠 레벨 행 대신 설비별 감축표와 생산 부담 비용으로 "비용 대비 감축이 큰 단계부터" 골라 ΔP를 채움. 선형에서 시작, 안 되면 비선형. 2차 자문의 AI 그룹핑 자리
4
구간 초반에 얕게 누를지 나중에 세게 누를지를 구간 전체로 판단하는 강화학습. 과거 데이터 시뮬레이터 안에서만 학습
부하적응 설비가 피크 행에도 등록되어 있으면, 부하적응 스텝 시험에서 정한 안전 하한을 03의 하한으로 그대로 씁니다(통합안 2장).
M6
안전: 풀 때 확인하고, 거꾸로 오르지 않게
1단계 · 규칙
P_end+ 해제
풀기 전에 "P_end + 복귀kW × 남은 시간 ÷ 0.25h + 20kW"가 그 레벨 임계보다 낮을 때만 해제. 새 파라미터는 해제 여유 하나. 복귀kW는 처음엔 제한 직전 kW − 현재 kW, 로그가 쌓이면 실측. P2 해결
·
가동률 역상승 방지
긴급 피크로 D1010에 쓸 값 = min(행 가동률, 현재 정상가동률). 설정 화면과 AI 결과 모두에서 피크 행 값보다 높아지지 않음. P6 해결 가정: 운영 의도 확인 필요
구간 말미
남은 시간 < 남은 후보 수 × 간격이면 간격을 건너뛰고 한 번에 거는 규칙(후보, 미검증) 3층
유지
기동 유예, 부하적응 OFF 확인 후 피크 ON(Break-before-Make), AI 하트비트 해제는 지금 그대로
M7
효과 검증
0~2단계
그림자 지표
놓친 구간(구간 평균이 목표를 넘었는데 레벨이 늦게 오름), 불필요 제어 시간(넘지 않을 구간에서 제어한 시간), 레벨 변경 횟수(흔들림)
감축표
M1 로그의 변경 전후 kW로 설비별 "가동률 → 실제 kW 비율" 곡선과 응답 시간을 하루 1회 갱신. 비율은 가동률n/3꼴(n = Hz 지수, 팬류 n ≈ 3이면 가동률 그대로, 정토크 n ≈ 1이면 가동률1/3) 지도
회피 피크
구간마다 Σ(감축kW × 제어시간) ÷ 0.25h. 「AI 도입 지도」 절감 리포트로
4
실행 계획
순서
작업
제어 변경
산출물
0-1
제어 로그에 걸린 레벨 행 기록(P7)
없음
레벨 행까지 복원되는 로그
0-2
로그 확장(변경 전후 kW), 총전력 10초 보관
없음
감축표 재료
1-1
별도 15분 누적기 + 층 1 계산 + 공유 테이블 + 화면
없음
"이번 구간이 어떻게 끝날지" 화면
1-2
P_end+ 그림자 기록 2주
없음
현재 방식과 비교표
1-3
P_end+ 켜기, 가동률 역상승 방지
레벨 판정·해제
불필요 제어 감소
2-1
감축표 자동 생성
없음
설비별 실측 감축
2-2
ΔP만큼 동시 제어(그림자 → 켜기)
제어 대수
늦게 거는 문제 해소
3-1
AI 입력에서 진행 중 블록 분리(P8), 남은 구간 예측 그림자
없음
예측 오차 비교
3-2
남은 구간 예측을 P_예측으로, 할당 최적화 그림자 → 켜기
예측·할당
모듈별 AI 전환
5
확인 필요
걸고 나서 kW가 안정되기까지 몇 초인지(0단계 로그로 실측). 가동률이 전력 비율이라는 점은 PLC 시뮬레이터로 확인됨(1-4)
한전 15분 계량 구간과 서버 구간의 정렬
긴급 피크 값이 정상가동률보다 높을 때 운영 의도(낮은 쪽을 쓰는 것이 맞는지)
현장별 제어 간격(데모 61초, 개발 20초, 자동 생성 기본값 3600초)
제어 로그에 칸을 추가할 때 웹 제어 이력 화면과 DB 백업·마이그레이션 영향
한 줄 정리
지금 피크제어는 순간값으로 15분 평균을 간접적으로 지키고 있고, 여력이 충분하면 대부분 막습니다. 먼저 기록을 바로잡고, 15분 예산으로 "덜 누르게" 바꾼 뒤, 감축표가 생기면 필요한 만큼 한 번에 걸고, 마지막에 예측과 할당을 한 모듈씩 AI로 바꿉니다.
그림 5. 늦게 들어온 부하. 앞 10분 850kW, 뒤 5분 1,100kW. 제어하지 않아도 933.3kW로 넘지 않는 구간인데, 현재 방식은 순간값만 보고 10분 이후를 눌러 903.7kW로 끝냅니다. P_end 계열은 누르지 않습니다. 불필요 제어가 줄어드는 대표 장면입니다. 현재P_end
그림 6. 초반 스파이크. 처음 2분 1,150kW, 이후 950kW. P_예측(최근 3분 평균)이 "스파이크가 계속된다"고 가정해서 P_end 쪽이 더 오래 누릅니다. 금방 끝나는 기동 피크인지 아는 것은 계산이 아니라 예측의 문제라서, 피크 위험 시간표나 예측 AI(6장)로 다룰 부분입니다. 현재P_end