아두이노와 노키아 5110 LCD로 만드는 DIY 전압계 - 단계별 가이드
부품 및 소모품
부품
수량
비고
아두이노 우노 (Arduino UNO)
1
전압 센서 모듈 (범용)
1
0-25V DC 측정 가능
노키아 5110 LCD 디스플레이
1
PCD8544 컨트롤러
브레드보드 (소형)
1
점퍼 와이어
1세트
프로젝트 비용은 약 10달러(약 13,000원)로 매우 저렴합니다.
앱 및 온라인 서비스
프로젝트 소개
이 튜토리얼에서는 아두이노와 큰 화면의 노키아 5110 LCD 디스플레이로 전압계(Voltmeter) 를 만드는 방법을 보여드립니다.
전압계 제작은 훌륭한 학습 경험입니다. 이 프로젝트를 완료하면 전압계의 작동 원리를 이해하고, 옴의 법칙 지식을 복습하며, 아두이노 플랫폼이 얼마나 강력한지 직접 체험할 수 있습니다. 이 프로젝트를 기반으로 향후 더 복잡한 프로젝트도 쉽게 만들 수 있게 됩니다.
이 장치로 다양한 전자 회로의 DC 전압을 측정하거나 아두이노 프로젝트의 배터리 상태를 모니터링할 수 있습니다. 또한 습득한 지식으로 맞춤형 전압 센서를 제작해 자신에게 맞는 전압계를 만들 수도 있습니다.
1단계: 부품 준비
아두이노 우노
전압 센서 모듈
노키아 5110 LCD 디스플레이
소형 브레드보드
점퍼 와이어 몇 개
2단계: 전압 센서 모듈 이해하기
이 센서는 0-25V DC 전압을 측정 할 수 있으며, 내부적으로 단 두 개의 저항만으로 구성 된 전압 분배기(Voltage Divider) 회로입니다. 직접 만들 수도 있고, 1달러 미만으로 구매할 수도 있습니다.
전압 분배기 원리: Vout = Vin × R2/(R1+R2)
이 모듈에서 R1 = 30,000Ω, R2 = 7,500Ω입니다. 입력에 25V를 가하면 출력에서 5V가 나옵니다. 이는 아두이노 아날로그 핀이 처리할 수 있는 최대 전압입니다. 25V를 초과하면 아날로그 핀이 손상될 수 있습니다. 0V 입력 시 0V 출력이므로, 0-25V 입력이 0-5V 출력으로 선형 변환됩니다.
아두이노 우노는 10비트 ADC(1024 단계)를 가지므로, 이 센서로 달성 가능한 해상도는 약 25mV 입니다. 아두이노 듀(12비트 ADC)를 사용하면 더 높은 해상도를 얻을 수 있지만, 3.3V 로직 레벨이므로 별도의 전압 센서를 제작해야 합니다.
3단계: 노키아 5110 LCD
노키아 5110은 제가 아두이노 프로젝트에서 가장 좋아하는 디스플레이입니다.
노키아 5110 LCD 사용법에 대한 자세한 튜토리얼 영상을 준비했습니다. 영상을 꼭 시청해보시길 권장합니다.
4단계: 전압계 조립
전압 센서 연결
- 핀 → 아두이노 GND
+ 핀 → 미연결
S 핀 → 아두이노 아날로그 핀 A0
노키아 5110 LCD 연결
RST → 디지털 핀 12
CE → 디지털 핀 11
DC → 디지털 핀 10
DIN → 디지털 핀 9
CLK → 디지털 핀 8
VCC → 아두이노 3.3V
LIGHT → 아두이노 GND (백라이트 켜기)
GND → 아두이노 GND
모든 부품 연결이 완료되면 코드를 업로드합니다. 스플래시 화면이 몇 초간 표시된 후 전압 측정을 시작할 수 있습니다.
5단계: 프로젝트 코드
코드는 두 파일로 구성됩니다:
ui.c - 화면 UI 그래픽 데이터
VoltMeter.ino - 메인 프로그램
ui.c - 프로젝트용 그래픽
노키아 5110에 표시될 스플래시 아이콘과 전압계 UI 아이콘의 바이너리 데이터가 들어 있습니다. 커스텀 그래픽을 아두이노 프로젝트에 로드하는 방법은 첨부된 영상을 참조하세요.
VoltMeter.ino - 메인 프로그램
노키아 5110 라이브러리를 포함하고 변수를 선언한 후 디스플레이를 초기화합니다. 스플래시 화면을 3초간 표시한 뒤 UI 아이콘을 한 번 그리고, 1초마다 센서에서 아날로그 값을 읽어 전압을 계산해 화면에 표시합니다.
핵심은 다음 전압 읽기 함수입니다:
float readVoltage() {
sensorValue = analogRead(sensorPin);
vout = (sensorValue * 5.0) / 1024.0;
vin = vout / (R2 / (R1 + R2));
return vin;
}
이 함수는 센서 값을 읽어 0-25V 범위의 전압으로 변환합니다. 직접 만든 전압 센서를 사용하는 경우 R1, R2 변수를 본인의 저항 값으로 변경해야 합니다.
전압 값을 읽은 후 문자열로 변환해 화면에 출력합니다. 전체 코드는 프로젝트 웹페이지(educ8s.tv/arduino-voltmeter-project/)에서 최신 버전을 다운로드할 수 있습니다.
6단계: 프로젝트 테스트
충전식 AA 배터리, 18650 배터리, 12V 알람 배터리 등으로 테스트했습니다. 전문 멀티미터와 비교해도 측정된 값이 매우 근접했습니다.
멀티미터와 비교 테스트
이 프로젝트는 오픈소스 하드웨어와 소프트웨어가 무엇을 할 수 있는지 보여주는 훌륭한 예입니다. 몇 분 만에 이렇게 인상적인 프로젝트를 만들 수 있다니! 초보자에게 이상적이며, 앞서 말했듯 훌륭한 학습 경험이 됩니다.
여러분의 의견을 듣고 싶습니다. 유용하다고 생각하시나요? 개선할 점이 있을까요? 댓글로 아이디어를 공유해주세요!
코드
VoltMeter.ino
//////////////////////////////////////////////
// Arduino Voltmeter Project
// with NOKIA 5110 LCD
// https://www.educ8s.tv
/////////////////////////////////////////////
#include // 라이브러리: https://www.rinkydinkelectronics.com/library.php?id=47
LCD5110 lcd(8, 9, 10, 12, 11); // CLK, DIN, DC, RST, CE
extern unsigned char BigNumbers[];
extern uint8_t ui[];
extern uint8_t startScreen[];
float voltage = 0.0;
int sensorPin = A0;
float sensorValue = 0.0f;
String voltageString = "0.0";
int stringLength = 0;
float vout = 0.0;
float vin = 0.0;
float R1 = 30000.0;
float R2 = 7500.0;
void setup() {
Serial.begin(9600);
lcd.InitLCD();
lcd.drawBitmap(0, 0, startScreen, 84, 48);
lcd.update();
delay(3000);
lcd.setFont(BigNumbers);
delay(1000);
}
void loop() {
lcd.clrScr();
lcd.drawBitmap(0, 0, ui, 84, 48);
voltage = readVoltage();
Serial.println(voltage);
voltageString = String(voltage, 1); // 소수점 1자리
stringLength = voltageString.length();
displayVoltage(stringLength);
lcd.update();
delay(1000);
}
float readVoltage() {
sensorValue = analogRead(sensorPin);
vout = (sensorValue * 5.0) / 1024.0;
vin = vout / (R2 / (R1 + R2));
return vin;
}
void displayVoltage(int length) {
switch (length) {
case 3: lcd.print(voltageString, 14, 19); break; // 예: 3.3V
case 4: lcd.print(voltageString, 2, 19); break; // 예: 12.5V
default: lcd.print(voltageString, 2, 19); break;
}
}
ui.c (UI 그래픽 데이터)
#include
const unsigned char ui[] PROGMEM = {
// 전압계 UI 비트맵 데이터 (84x48 픽셀)
0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11, 0x31, 0xF1, 0xD1, 0x01, 0x01,
0x81, 0xF1, 0x11, 0x11, 0xC1, 0xE1, 0x11, 0x11, 0x11, 0x31, 0xE1, 0xC1, 0x01, 0x01, 0x11, 0xF1,
0xF1, 0x11, 0x01, 0x01, 0x01, 0x31, 0x11, 0x11, 0xF1, 0xF1, 0x11, 0x11, 0x31, 0x01, 0x01, 0x01,
0x01, 0x81, 0x61, 0x31, 0xF1, 0xC1, 0x01, 0x01, 0x01, 0xC1, 0xE1, 0x21, 0x11, 0x11, 0x11, 0x31,
0x31, 0x01, 0x11, 0xF1, 0xF1, 0x91, 0x91, 0x91, 0x31, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
0xC0, 0xC3, 0xCF, 0xCC, 0xC3, 0xC0, 0xC0, 0xC0, 0xC3, 0xC7, 0xCC, 0xC8, 0xC8, 0xC8, 0xC7, 0xC3,
0xC0, 0xC0, 0xC8, 0xCF, 0xCF, 0xC8, 0xC8, 0xC8, 0xCC, 0xC0, 0xC0, 0xC8, 0xCF, 0xCF, 0xC8, 0xC0,
0xC0, 0xC0, 0xC0, 0xC8, 0xCC, 0xCB, 0xC1, 0xC1, 0xC1, 0xCF, 0xCE, 0xC8, 0xC0, 0xC3, 0xC7, 0xCC,
0xC8, 0xC8, 0xC9, 0xCF, 0xC7, 0xC1, 0xC8, 0xCF, 0xCF, 0xC8, 0xC8, 0xC8, 0xCC, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF
// ... (이하 생략, 전체 데이터는 원문 참조)
};
const unsigned char startScreen[] PROGMEM = {
// 스플래시 화면 비트맵 데이터
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFC, 0xFC, 0xFC, 0xFC,
0xFC, 0x7C, 0x1C, 0x04, 0x00, 0x20, 0xE0, 0xE0, 0x20, 0x00, 0x00, 0x20, 0xE0, 0x20, 0x80, 0xC0,
0x60, 0x20, 0x20, 0x20, 0x60, 0xC0, 0x80, 0x20, 0xE0, 0xE0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xE0, 0x60, 0x20, 0xE0, 0xE0, 0x20, 0x60, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0x00,
0x00, 0x00, 0x80, 0xC0, 0x60, 0x20, 0x20, 0x20, 0x60, 0xE0, 0x00, 0x20, 0xE0, 0xE0, 0x20, 0x20,
0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF,
0x3F, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3F, 0x38, 0x38, 0x07, 0x00, 0x00,
0x0F, 0x1F, 0x30, 0x20, 0x20, 0x20, 0x30, 0x1F, 0x0F, 0x20, 0x3F, 0x3F, 0x20, 0x20, 0x30, 0x38,
0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x3F, 0x20, 0x00, 0x00, 0x20, 0x38, 0x27, 0x04, 0x04, 0x27,
0x3F, 0x3C, 0x20, 0x0F, 0x1F, 0x30, 0x20, 0x20, 0x24, 0x3C, 0x3C, 0x04, 0x20, 0x3F, 0x3F, 0x22,
0x22, 0x22, 0x20, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0xFE, 0xFF, 0xFF, 0x3F,
0x0F, 0x83, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0x38, 0x00, 0x00,
// ... (이하 생략)
};