이 아두이노 튜토리얼에서는 MIT 앱 인벤터 온라인 애플리케이션을 사용해 아두이노 제어용 커스텀 안드로이드 애플리케이션을 만드는 방법을 배웁니다. 아래 비디오를 시청하거나 작성된 튜토리얼을 읽어보세요.
개요
이 튜토리얼에는 두 가지 예제가 있습니다. 첫 번째는 간단한 LED 제어, 두 번째는 스마트폰으로 스테퍼 모터 제어. 이전 튜토리얼에서 HC-05 블루투스 모듈로 아두이노 보드와 스마트폰 간 블루투스 통신 방법과 첫 번째 예제에 필요한 아두이노 코드를 이미 설명했습니다.
아두이노 코드
코드 개요: 시리얼 포트로 스마트폰에서 오는 데이터 수신해 'state' 변수에 저장. 문자 '0' 수신(스마트폰에서 'LED: OFF' 버튼 누름) 시 LED 끄고 "LED: OFF" 문자열을 스마트폰으로 전송. 문자 '1' 수신 시 LED 켜고 "LED: ON" 전송.
/* 아두이노와 HC-05 블루투스 모듈 튜토리얼
* by Dejan Nedelkovski, www.HowToMechatronics.com
*/
#define ledPin 7
int state = 0;
void setup() {
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
Serial.begin(38400); // 블루투스 모듈 기본 통신 속도
}
void loop() {
if (Serial.available() > 0) {
state = Serial.read();
}
if (state == '0') {
digitalWrite(ledPin, LOW);
Serial.println("LED: OFF");
state = 0;
} else if (state == '1') {
digitalWrite(ledPin, HIGH);
Serial.println("LED: ON");
state = 0;
}
}코드 언어: Arduino (arduino)
이제 이 문자 '0', '1'을 버튼 누름 시 전송하고 아두이노에서 오는 문자열을 수신할 커스텀 안드로이드 앱을 만들어야 합니다.
MIT 앱 인벤터
MIT 앱 인벤터 웹사이트에서 "Create apps!" 버튼 클릭해 온라인 빌드 애플리케이션 로그인. 지메일 계정 필요. 로그인 후 첫 프로젝트 생성. 디자인 화면 모습이며 이제 앱 제작 시작.
그 전에 스마트폰을 이 프로젝트에 연결해 실시간으로 앱 모양 확인 가능. 먼저 플레이 스토어에서 MIT AI2 Companion 앱 다운로드 설치. 온라인 에디터의 Connect 메뉴에서 AI Companion 선택, 바코드 스캔하거나 코드 입력하면 온라인 에디터와 스마트폰 앱 연결됨.
이제 온라인 에디터 화면에 버튼 삽입하면 스마트폰에도 실시간으로 나타남. 스마트폰 대신 컴퓨터에 안드로이드 에뮬레이터 설치해 같은 방식 사용 가능. 에뮬레이터 설정 방법은 웹사이트 참조.
앱 제작 – 예제 1
첫 번째 예제 제작 시작. 프로그램 레이아웃부터. 레이아웃 팔레트에서 HorizontalArrangement 추가, 높이/너비/정렬 속성 설정. UserInterface 팔레트에서 ListPicker 추가, 이미지 첨부. ListPicker는 스마트폰이 연결할 블루투스 장치 선택용.
다른 HorizontalArrangement에 Label 배치. 이 라벨은 블루투스 모듈 연결 여부 표시용, 초기 텍스트 "Not Connected". 다음 라벨은 LED 상태 표시용, 초기 상태 "LED: OFF". 'Turn On', 'Turn Off' 버튼 두 개 추가로 LED 제어. 컴포넌트 이름 변경해 블록 에디터에서 쉽게 인식하도록 함. 남은 건 블루투스 클라이언트(비가시 컴포넌트)와 실시간 연결 상태 표시용 시계 추가.
블록 에디터
블록 에디터에서 프로그램에 생명을 불어넣습니다. 왼쪽에서 앞서 추가한 컴포넌트 관련 블록과 함수 사용 가능.
BluetoothList ListPicker부터. 'BeforePicking' 블록 추가, 'set Bluetooth Elements' 블록 연결. BluetoothClient 블록에서 'BluetoothClient AddressesAndNames' 블록 추가. 이 블록 세트는 휴대폰과 이미 페어링된 블루투스 장치 목록 설정, ListPicker "Connect Button" 클릭 시 페어링된 장치 목록 표시.
특정 블루투스 모듈 선택 후 동작 설정. BluetoothClient 블록에서 'call BluetoothClient .Connect address' 블록 추가, 'BluetoothList Selection' 블록 연결 → 선택한 블루투스 주소로 연결.
Clock 블록에서 ".Timer" 블록 추가. 이 안에서 "set Text" 블록으로 "Connected" 라벨에 실시간 연결 여부 표시.
두 버튼에 생명 부여. "TurnOn_Button" 클릭 시 BluetoothClient 함수 "Send1ByteNumber"로 아두이노 블루투스 모듈에 숫자 전송. 여기서는 ASCII표 기준 문자 '1'에 해당하는 49 전송 → LED 켜짐. 직후 "ReceiveText" 함수로 아두이노에서 보내는 문자열 수신해 "LED_Status" 라벨에 설정.
"TurnOff_Button"도 동일, 전송 숫자만 48(문자 '0')로 변경. 이제 스마트폰에 프로그램 다운로드 설치. "Build" 메뉴에서 컴퓨터 저장 후 전송하거나 QR 코드 스캔으로 온라인 다운로드. 예제 시연.
위 MIT 앱 인벤터 프로젝트 다운로드 파일:
BluetoothTest.aia
1 file(s) 5.16 KB Download
스테퍼 모터 제어 예제
두 번째 예제, 스테퍼 모터 제어. 화면 상단에 이전 예제와 같은 블루투스 연결 컴포넌트. Canvas 컴포넌트로 그리기 및 이미지 삽입. 미리 그린 투명 이미지 두 개 삽입: 고정될 게이지 이미지, 회전할 포인터 이미지. Manual/Auto(연속 실행) 전환용 체크 버튼, 회전 방향 변경 버튼. 하단에 스테퍼 모터 회전 속도 조절 슬라이더.
이 예제의 블록과 아두이노 코드. 블록 에디터에서 블루투스 연결 블록은 이전 예제와 동일.
포인터 이미지 회전에는 ImageSprite 함수 ".PointInDirection" 사용, 캔버스 터치된 X, Y 좌표로 0° 위치에서 회전. 동시에 회전된 ImageSprite 헤딩을 위 텍스트 라벨에 설정. 이후 직접 만든 프로시저(함수) 호출, 실제로는 10ms 지연.
마지막으로 헤딩 값을 텍스트로 아두이노에 전송("SendText" 블루투스 함수). 이 값은 아두이노에서 받아 스테퍼 모터를 해당 각도로 회전.
CheckBox 블록: 체크 시 "Auto" 텍스트 전송 → 아두이노에서 스테퍼 모터 연속 회전 활성화. 이 모드에서 "Reverse" 버튼 누르면 "Reverse" 텍스트 전송 → 모터 회전 방향 변경. 슬라이더 위치 변경 시 현재 값 전송 → 회전 속도 변경. 체크 해제 시 수동 모드 복귀. 예제 시연.
위 MIT 앱 인벤터 프로젝트 다운로드 파일과 프로젝트에 사용된 두 이미지:
StepperMotorTest.aia
1 file(s) 60.96 KB Download
Stepper Motor Gauge and Pointer Images
1 file(s) 27.34 KB Download
두 번째 예제의 아두이노 코드:
/* HC-05 블루투스 모듈로 스테퍼 모터 제어
* by Dejan Nedelkovski, www.HowToMechatronics.com
*/
// 변수 정의
const int stepPin = 7;
const int dirPin = 6;
String state = "";
int currentHeading = 0;
int currentAngle = 0;
int lastAngle = 0;
int angle = 0;
int rotate = 0;
int runContinuously = 0;
String mode = "Manual";
boolean dirRotation = HIGH;
int rotSpeed = 1500;
void setup() {
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
Serial.begin(38400);
}
void loop() {
delayMicroseconds(1);
if (Serial.available() > 0) {
state = Serial.readString();
}
// Auto 버튼 눌림
if (mode == "Auto") {
if (state == "Reverse") {
delay(10);
if (dirRotation == HIGH) dirRotation = LOW;
else dirRotation = HIGH;
digitalWrite(dirPin, dirRotation);
delay(10);
state = "";
}
rotSpeed = state.toInt();
if (rotSpeed >= 300 && rotSpeed <= 3000) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(rotSpeed);
digitalWrite(stepPin, LOW);
delayMicroseconds(rotSpeed);
} else {
digitalWrite(stepPin, HIGH);
delayMicroseconds(1500);
digitalWrite(stepPin, LOW);
delayMicroseconds(1500);
}
if (state == "Manual") {
mode = state;
}
}
// 수동 모드
else if (mode == "Manual") {
currentHeading = state.toInt();
if (currentHeading < 0) {
currentHeading = 360 + currentHeading;
}
currentAngle = map(currentHeading, 0, 359, 0, 200);
digitalWrite(dirPin, HIGH);
if (currentAngle != lastAngle) {
if (currentAngle > lastAngle) {
rotate = currentAngle - lastAngle;
for (int x = 0; x < rotate; x++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(500);
digitalWrite(stepPin, LOW);
delayMicroseconds(500);
}
}
if (currentAngle < lastAngle) {
rotate = lastAngle - currentAngle;
digitalWrite(dirPin, LOW);
for (int x = 0; x < rotate; x++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(500);
digitalWrite(stepPin, LOW);
delayMicroseconds(500);
}
}
}
lastAngle = currentAngle;
if (state == "Auto") {
mode = state;
}
}
}코드 언어: Arduino (arduino)