J.A.R.V.I.S. - Arduino로 구동하는 스마트 홈 가상 비서
필요한 부품 및 소모품
| Arduino 101 |
1개 |
| Arduino 4 릴레이 쉴드 |
1개 |
| Arduino GSM 쉴드 V2 |
1개 |
필요한 도구 및 기계
앱 및 온라인 서비스
- Unity
- Android Studio
- Vuforia
- Adobe Illustrator
- Arduino IDE
프로젝트 소개
왜 스마트 홈 문제를 해결하려 했나?
무엇이 새로운가?
왜 이 프로젝트를 만들기로 했나?
작동 원리
디지털 에너지 미터
AI 가상 비서
신호 흐름:
- 안드로이드 앱으로 음성 입력
- 안드로이드 앱에서 처리
- 블루투스를 통해 암호화된 데이터를 Arduino로 전송
- Arduino 101에서 처리
- 릴레이로 디지털 신호 출력
핀 연결:
- Pin 8 → PulseIn [디지털 입력] (에너지 미터)
- Pin 6 → IN1 → 팬 출력
- Pin 4 → IN2 → 조명 출력
- Pin 5 → IN3 → 커피 메이커 출력
에너지 미터 연결:
에너지 미터를 전원에 연결합니다.
에너지 미터 내부의 LDR이 외부 빛을 받지 않도록 검은 테이프로 덮습니다.
중성선은 부하에 직접 연결하고, 상선은 릴레이를 통해 연결합니다.
LDR에서 나온 선을 카운터 회로로 연결합니다.
카운터 회로 출력을 코드의 pin 8(pulsepin)에 연결합니다.
Arduino 101의 TX, RX 핀을 GSM 모듈의 RX, TX 핀에 연결합니다.
코드 업로드 후 보드에 전원을 공급합니다.
회로도
회로도 이미지 참조
사용된 하드웨어 및 장비
- 에너지 미터 내부: LDR (조도 의존 저항)
- GSM 모듈
- 카운터 회로: 가변저항, IC LM358N
- Arduino 101
- 블루투스 HC-05 모듈
- 4채널 12V 10A 릴레이 제어 보드 (옵토커플러 내장, PIC AVR ARM용)
프로그래밍 플랫폼
- Arduino 101 프로그래밍: Arduino IDE
- 안드로이드 앱 개발: Android Studio (Java, XML)
- 데이터베이스 연동: Google Firebase
- 증강현실: Unity + Vuforia SDK
구현
- 모든 구성요소가 Arduino에 판독값을 제공하며, 이를 문자 코드로 변환하여 바이트를 효율적으로 전송합니다. 무한 루프에서 각 판독값이 문자에 대응됩니다.
- 컴퓨터에서 Arduino가 시리얼 포트로 전송하는 데이터를 수신하는 코드가 실행되어야 합니다.
- 안드로이드 앱은 Android Studio로 개발했으며, 음성-텍스트 변환에 Google 표준 API를 사용합니다.
- 음성 인식에는 안드로이드 앱에서 화자 독립적 음성 인식을 위한 음향-음성 매개변수를 사용합니다.
- AI 가상 비서는 Python으로 CNN(합성곱 신경망) 등 딥러닝 기법을 사용하여 자연어 처리를 구현합니다.
- 증강현실 앱은 Unity IDE와 Vuforia SDK(모바일 기기용 AR SDK)로 개발했습니다.
비디오
프로젝트 시연 영상
유용한 링크
코드
디지털 에너지 판독 및 비용 계산용 Arduino 코드
이 코드는 Arduino에 연결된 가전제품의 소비 전력량을 구현합니다.
#include <LiquidCrystal.h>
LiquidCrystal lcd(7,6,5,4,3,2);
int led=13;
#define pulsein 8
unsigned int pusle_count=0;
float units=0;
unsigned int rupees=0;
unsigned int temp=0,i=0;
char str[70],flag1=0,flag2=0;
void setup() {
lcd.begin(16,2);
Serial.begin(9600);
pinMode(led, OUTPUT);
pinMode(pulsein, INPUT);
digitalWrite(pulsein, HIGH);
lcd.setCursor(0,0);
lcd.print("Wireless Energy");
lcd.setCursor(0,1);
lcd.print(" Meter ");
delay(2000);
lcd.clear();
lcd.print("By ");
delay(2000);
lcd.clear();
lcd.print("GSM Initilizing...");
gsm_init();
lcd.clear();
lcd.print("System Ready");
Serial.println("AT+CNMI=2,2,0,0,0");
init_sms();
send_data("System Ready");
send_sms();
delay(1000);
digitalWrite(led, LOW);
lcd.clear();
}
void loop() {
serialEvent();
units=rupees/5.0;
lcd.setCursor(0,0);
lcd.print("Units:");
lcd.print(units);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("Rupees:");
lcd.print(rupees);
lcd.print(" ");
read_pulse();
if(temp==1) { check(); }
}
void serialEvent() {
while(Serial.available()) {
if(Serial.find("#")) {
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
while (Serial.available()) {
char inChar=Serial.read();
str[i++]=inChar;
if(inChar=='*') { temp=1; return; }
}
}
}
}
void init_sms() {
Serial.println("AT+CMGF=1");
delay(200);
Serial.println("AT+CMGS=\"INSERT MOBILE NUMBER HERE\"");
delay(200);
}
void send_data(String message) {
Serial.println(message);
delay(200);
}
void send_sms() {
Serial.write(26);
}
void read_pulse() {
if(!digitalRead(pulsein)) {
digitalWrite(led, HIGH);
units++;
rupees=units*5;
while(!digitalRead(pulsein));
digitalWrite(led,LOW);
}
}
void check() {
if(!(strncmp(str,"units",5))) {
Serial.println("AT+CMGF=1");
delay(200);
Serial.println("AT+CMGS=\"INSERT MOBILE NUMBER HERE\"");
delay(200);
lcd.setCursor(0,1);
send_data("Energy Meter Unit:");
Serial.println(units);
send_data("\nRupees:");
Serial.println(rupees);
delay(200);
Serial.write(26);
flag1=1; flag2=1; temp=0;
}
}
void message_sent() {
lcd.clear();
lcd.print("Message Sent.");
delay(1000);
}
void gsm_init() {
lcd.clear();
lcd.print("Finding Module..");
boolean at_flag=1;
while(at_flag) {
Serial.println("AT");
while(Serial.available()>0) {
if(Serial.find("OK")) at_flag=0;
}
delay(1000);
}
lcd.clear();
lcd.print("Module Connected..");
delay(1000);
lcd.clear();
lcd.print("Disabling ECHO");
boolean echo_flag=1;
while(echo_flag) {
Serial.println("ATE0");
while(Serial.available()>0) {
if(Serial.find("OK")) echo_flag=0;
}
delay(1000);
}
lcd.clear();
lcd.print("Echo OFF");
delay(1000);
lcd.clear();
lcd.print("Finding Network..");
boolean net_flag=1;
while(net_flag) {
Serial.println("AT+CPIN?");
while(Serial.available()>0) {
if(Serial.find("+CPIN: READY")) net_flag=0;
}
delay(1000);
}
lcd.clear();
lcd.print("Network Found..");
delay(1000);
lcd.clear();
}
JARVIS 릴레이 연결 구현 Arduino 코드
안드로이드 앱과 Arduino 간 시리얼 블루투스 문자 전송을 구현한 코드입니다.
#define CH3 7
#define CH4 4
#define CH5 5
#define CH6 6
void setup() {
Serial.begin(9600);
pinMode(CH3, OUTPUT);
pinMode(CH4, OUTPUT);
pinMode(CH5, OUTPUT);
pinMode(CH6, OUTPUT);
digitalWrite(CH3, HIGH);
digitalWrite(CH4, HIGH);
digitalWrite(CH5, HIGH);
digitalWrite(CH6, HIGH);
delay(2000);
}
void loop() {
delay(100);
if(Serial.available()) {
char c = Serial.read();
Serial.print(c);
if(c=='b') { /* coffee off */ }
else if(c=='c') { digitalWrite(CH4, LOW); delay(100); } // light on
else if(c=='d') { digitalWrite(CH6, LOW); delay(100); } // fan on
else if(c=='k') { digitalWrite(CH5, LOW); delay(100); } // coffee on
else if(c=='g') { digitalWrite(CH5, HIGH); delay(100); } // coffee off
else if(c=='e') { digitalWrite(CH4, HIGH); delay(100); } // light off
else if(c=='f') { digitalWrite(CH6, HIGH); delay(100); } // fan off
else if(c=='z') { // goodbye
digitalWrite(CH6, HIGH);
digitalWrite(CH4, HIGH);
digitalWrite(CH3, HIGH);
digitalWrite(CH5, HIGH);
delay(500);
digitalWrite(CH5, LOW);
delay(500);
digitalWrite(CH5, HIGH);
delay(500);
digitalWrite(CH5, LOW);
delay(500);
digitalWrite(CH5, HIGH);
delay(10000);
}
}
}
커스텀 파트 및 인클로저
안드로이드 앱 APK 파일 제공 (JARVIS 증강현실 앱, 메인 JARVIS 앱)
회로도
회로도 이미지 및 사용 설명서 포함