nano_ardule_midi_controller:pc900v
Table of Contents
PC900 optocoupler
기본 자료
PC900V 데이터시트
다음 그림의 출처: http://midi.teragonaudio.com/hardware/pc_intfc.htm
(상단에서 본 모습, 핀1 표시 점 기준) ┌───────┐ Anode |1 6| Vcc (+5V) Cathode |2 5| GND (Emitter) NC |3 4| Vout (Collector) └───────┘
핀 기능 요약
- Pin 1 : LED Anode (+, DIN4에서 220Ω 직렬 후 연결)
- Pin 2 : LED Cathode (–, DIN5와 연결)
- Pin 3 : NC (사용 안 함)
- Pin 4 : Collector (출력, 풀업 후 아두이노 RX로)
- Pin 5 : Emitter (GND)
- Pin 6 : Vcc (+5V)
PC900V Drop-in Replacement
PC900V는 샤프(SHARP, 현재는 Vishay 등에 승계)에서 나온 포토커플러로, 포토트랜지스터 출력이며 약 80–100 kbps 정도의 응답 속도를 가집니다. MIDI IN과 같은 31.25 kbps 신호에서는 충분히 동작하지만, 단종/구하기 어려운 경우가 있어 대체품을 찾게 됩니다.
1. 핀 호환 Drop-in 대체품
- Vishay VO618A / VO615A
→ PC900과 동일한 4핀 DIP 패키지, CTR 범위 유사.
- Toshiba TLP521
→ 흔한 범용 포토커플러, 속도는 MIDI용으로 충분.
- Everlight EL817
→ 국내외 유통량이 많음. CTR 넓고 속도는 약 50 kHz 수준으로 MIDI에 사용 가능.
2. MIDI용으로 자주 쓰이는 대체품
- 6N138 / 6N137
- 핀 배열은 다르지만 MIDI IN 회로 예제에서 가장 많이 사용됨.
- 6N138: CTR 높으나 응답이 느려 강한 풀업 저항(220Ω 수준)을 요구.
- 6N137: 더 빠른 디지털용, 내부 슈미트 트리거 내장 → TTL 레벨로 안정적.
- HCPL-0500, HCPL-0630
- 고속/저지연용. MIDI에는 다소 오버스펙이지만 안정적 동작.
3. 정리
- 핀 배열 그대로 교체 가능한 부품: VO618A, TLP521, EL817 등 4핀 DIP 계열.
- MIDI IN 전용으로는 6N138/6N137이 사실상 업계 표준.
- 단순 교체가 목적이라면 VO618A 같은 4핀 DIP가 가장 무난.
Arduino UNO 기반 PC900V 옵토커플러 테스터 (I2C 2004 LCD 표시)
아두이노 우노(UNO)로 PC900V(포토트랜지스터형 옵토커플러)를 단품 점검하고, 측정 결과를 I2C 20×4 LCD(2004)에 표시하는 예제입니다. Phase1(저속 ON/OFF 논리 확인)과 Phase2(1 kHz/5 kHz 토글 응답 통계)를 지원합니다.
1. 준비물
- Arduino UNO 보드
- PC900V (또는 EL817/TLP521 등 4핀 포토트랜지스터형 옵토커플러)
- I2C 20×4 LCD 모듈 (주소 0x27 또는 0x3F)
- 저항: 220Ω(LED 직렬), 1kΩ~2.2kΩ(출력 풀업/로드 RL)
- 점퍼 케이블, 브레드보드
2. 배선
D9로 PC900V의 LED를 구동하고, D2(INT0)로 포토트랜지스터 출력을 읽습니다. (I2C 20×4 LCD를 사용할 경우 A4/A5 배선 예시도 아래에 포함)
Arduino UNO PC900V (6pin DIP) ============ ================== D9 (디지털 출력) -----[220Ω]----------> Pin1 (Anode, LED+) GND ---------------------------------> Pin2 (Cathode, LED-) +5V ---------------------------------> Pin6 (Vcc) GND ---------------------------------> Pin5 (Emitter, GND) D2 (디지털 입력, INT0) <------------+-- Pin4 (Collector, Output) | [RL = 1kΩ~2.2kΩ Pull-up] | +5V
요약:
- UNO D9 → 220Ω → PC900V Pin1 (LED+), Pin2은 GND.
- UNO +5V → Pin6 (Vcc), UNO GND → Pin5 (Emitter).
- PC900V Pin4 (Collector) → UNO D2 입력, 그리고 풀업저항(RL) 을 통해 +5V에 연결.
- 필요 시 Pin4→(74HC14 1게이트)→D2 로 신호 정형 권장.
- UNO의 0,1번 핀(RX/TX)은 USB 시리얼과 충돌하므로 사용하지 않습니다.
(선택) I2C 20×4 LCD 연결 예시
테스트 결과를 LCD에 표시하려면 아래처럼 I2C LCD를 추가하세요. (주소 0x27 또는 0x3F)
UNO A4 (SDA) -------------------- LCD SDA UNO A5 (SCL) -------------------- LCD SCL UNO +5V ------------------------- LCD VCC UNO GND ------------------------- LCD GND
3. 기대 동작
- LED ON(=D9 HIGH) → 트랜지스터 ON → D2가 LOW
- LED OFF(=D9 LOW) → 트랜지스터 OFF → D2가 HIGH
- Phase2에서 1 kHz/5 kHz 토글에 대해 엣지 개수와 HIGH/LOW 평균 펄스폭이 반주기 근처면 정상
4. 스케치 (I2C 2004 LCD 표시)
- 라이브러리: LiquidCrystal_I2C (주소 기본 0x27, 필요 시 0x3F로 변경)
- 시리얼 모니터(115200bps)는 선택 사항(디버깅용)
// Arduino UNO + I2C 2004 LCD: PC900V Optocoupler Tester // D9: drive(220Ω 통해 PC900V LED+), D2: sense(INT0, RL=1k~2.2kΩ로 +5V 풀업) // LCD: 20x4 I2C (addr 0x27). 필요 시 0x3F 등으로 변경. #include <Wire.h> #include <LiquidCrystal_I2C.h> #define LCD_ADDR 0x27 LiquidCrystal_I2C lcd(LCD_ADDR, 20, 4); const uint8_t DRIVE_PIN = 9; // Opto LED drive const uint8_t SENSE_PIN = 2; // Opto output sense (INT0) volatile uint32_t edgeCount = 0; volatile uint32_t lastEdgeUs = 0; volatile uint8_t lastState = 0; volatile uint32_t highMin = 0xFFFFFFFF, highMax = 0, highSum = 0, highCnt = 0; volatile uint32_t lowMin = 0xFFFFFFFF, lowMax = 0, lowSum = 0, lowCnt = 0; void onSenseEdge() { uint32_t now = micros(); uint8_t state = digitalRead(SENSE_PIN); // HIGH=1, LOW=0 uint32_t dt = now - lastEdgeUs; if (lastEdgeUs != 0) { if (state == LOW) { // 방금 HIGH->LOW: 직전 구간은 HIGH 구간 길이 if (dt < highMin) highMin = dt; if (dt > highMax) highMax = dt; highSum += dt; highCnt++; } else { // 방금 LOW->HIGH: 직전 구간은 LOW 구간 길이 if (dt < lowMin) lowMin = dt; if (dt > lowMax) lowMax = dt; lowSum += dt; lowCnt++; } } lastEdgeUs = now; lastState = state; edgeCount++; } void resetStats() { noInterrupts(); edgeCount = 0; lastEdgeUs = 0; lastState = digitalRead(SENSE_PIN); highMin = lowMin = 0xFFFFFFFF; highMax = lowMax = 0; highSum = lowSum = 0; highCnt = lowCnt = 0; interrupts(); } void lcdHeader(const char* phase) { lcd.clear(); lcd.setCursor(0,0); lcd.print("Opto Tester (UNO)"); lcd.setCursor(0,1); lcd.print(phase); } void showPhase1(bool ledOn, int senseVal) { lcd.setCursor(0,2); lcd.print("LED:"); lcd.print(ledOn ? "ON " : "OFF"); lcd.print(" SENSE:"); lcd.print(senseVal ? "HIGH" : "LOW "); lcd.setCursor(0,3); lcd.print("Expect ON->LOW, OFF->HIGH "); } void showPhase2Stats(uint32_t freqHz, uint32_t edges, uint32_t hMin, uint32_t hMax, uint32_t hAvg, uint32_t lMin, uint32_t lMax, uint32_t lAvg) { lcd.clear(); lcd.setCursor(0,0); lcd.print("Phase2 @"); lcd.print(freqHz); lcd.print("Hz Edg:"); lcd.print(edges); lcd.setCursor(0,1); lcd.print("HIGH us min/"); lcd.print(hMin); lcd.print(" max/"); lcd.print(hMax); lcd.setCursor(0,2); lcd.print("HIGH avg:"); lcd.print(hAvg); lcd.print(" "); lcd.setCursor(0,3); lcd.print("LOW avg:"); lcd.print(lAvg); lcd.print(" "); } void phase1_basicToggle(uint16_t ms = 500, uint8_t repeats = 6) { lcdHeader("Phase1: Slow Toggle"); for (uint8_t i=0; i<repeats; ++i) { digitalWrite(DRIVE_PIN, HIGH); delay(ms); showPhase1(true, digitalRead(SENSE_PIN)); digitalWrite(DRIVE_PIN, LOW); delay(ms); showPhase1(false, digitalRead(SENSE_PIN)); } } void phase2_edgeStats(uint32_t freqHz = 1000, uint32_t durationMs = 2000) { uint32_t halfPeriodUs = 1000000UL / (2 * freqHz); resetStats(); uint32_t start = millis(); bool level = false; while (millis() - start < durationMs) { level = !level; digitalWrite(DRIVE_PIN, level ? HIGH : LOW); delayMicroseconds(halfPeriodUs); } digitalWrite(DRIVE_PIN, LOW); delay(10); noInterrupts(); uint32_t ec = edgeCount; uint32_t hMin = (highCnt ? highMin : 0); uint32_t hMax = (highCnt ? highMax : 0); uint32_t hAvg = (highCnt ? (highSum / highCnt) : 0); uint32_t lMin = (lowCnt ? lowMin : 0); uint32_t lMax = (lowCnt ? lowMax : 0); uint32_t lAvg = (lowCnt ? (lowSum / lowCnt) : 0); interrupts(); showPhase2Stats(freqHz, ec, hMin, hMax, hAvg, lMin, lMax, lAvg); } void setup() { pinMode(DRIVE_PIN, OUTPUT); digitalWrite(DRIVE_PIN, LOW); pinMode(SENSE_PIN, INPUT); // 외부 RL(1k~2.2kΩ) 권장 attachInterrupt(digitalPinToInterrupt(SENSE_PIN), onSenseEdge, CHANGE); lcd.init(); lcd.backlight(); Serial.begin(115200); // 선택 사항(디버깅) Serial.println(F("== PC900V Optocoupler Tester (UNO + I2C 2004) ==")); } void loop() { phase1_basicToggle(500, 6); // Phase1: 느린 ON/OFF로 논리 확인 phase2_edgeStats(1000, 2000); // Phase2: 1 kHz 2초 측정 delay(1500); phase2_edgeStats(5000, 2000); // Phase2: 5 kHz 2초 측정(여유 확인) delay(3000); }
5. 운용 팁
- RL(출력 풀업/로드)은 1k~2.2kΩ 권장(속도/전류 밸런스 양호). 4.7kΩ도 가능하나 에지가 둔해질 수 있음.
- 파형이 불안정하면 74HC14(1게이트) 를 D2 앞에 추가.
- Phase2에서 1 kHz/5 kHz 측정 시 평균 펄스폭이 반주기(500 µs/100 µs) 근처이고 엣지 카운트가 안정적이면 정상.
- MIDI(31.25 kbps)는 비트 폭이 32 µs 수준으로, 본 테스트에서 5 kHz(100 µs 반주기)까지 안정적이면 기본 동작 마진은 충분한 편.
6. 문제 해결 체크리스트
- D9→220Ω→PC900V Anode(+) / Cathode(−)→GND 배선 재확인
- RL 값/배선 길이 확인(1k~2.2kΩ 권장)
- GND 공통, 전원 5 V 안정성 확인
- LCD 주소(0x27/0x3F) 확인 및 변경
- (선택) 74HC14로 신호 정형 후 D2로 입력
nano_ardule_midi_controller/pc900v.txt · Last modified: by hyjeong