드디어 완성된 모습.
모터고정이 불안정해서 다소 탁탁거리긴 하지만 뭐 작동엔 이상이 없다.
준비물
- 아두이노 UNO
- 모터쉴드
- HC-06 블루투스 모듈
—-아래는 옵션—-
- 16*2 LCD
- LCD 인터페이스 변환 어댑터, I2C로 전환 (원래 LCD는 포트낭비가 많은데 이걸 이용하면 4포트 밖에 안쓴다.)
간단히 모터쉴드와 블루투스 모듈만 있으면 되겠다. 모터쉴드는 꼭 저 모델아니더라도 모터 2개를 운용할 수 있으면 된다.
그리고 블루투스를 연결할 스마트폰 앱이 필요한데
안드로이드에는 BlueStick Control 이라는 잘 만들어진 앱이 있어서 이걸 사용했다.
다음은 소스.
#include <Wire.h> #include <LiquidCrystal_I2C.h> #include <SoftwareSerial.h> LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x20 for a 16 chars and 2 line display SoftwareSerial btSerial(11,12); // RX, TX of bluetooth const int moter1_ctrl = 2; const int moter1 = 3; const int moter2_ctrl = 4; const int moter2 = 5; const int kCodeUp = 56; const int kCodeDown = 50; const int kCodeLeft = 52; const int kCodeRight = 54; const int kCodeGrab = 67; const int kCodeRelease = 68; const int kRotateL = 69; const int kRotateR = 70; const int kCodeBtnUp = 48; int op_m1_run = LOW; int op_m2_run = LOW; int op_m1_direct = HIGH; int op_m2_direct = HIGH; int last_cmd = 0; void setup() { Serial.begin(9600); btSerial.begin(9600); lcd.init(); lcd.backlight(); lcd.print("Remote Car"); pinMode(moter1, OUTPUT); pinMode(moter1_ctrl, OUTPUT); pinMode(moter2, OUTPUT); pinMode(moter2_ctrl, OUTPUT); digitalWrite(moter1_ctrl, HIGH); digitalWrite(moter2_ctrl, HIGH); } String formatMotorStatus(String name, int run, int direct) { String str; str = name + ":"; str += run == HIGH ? " ON " : " OFF"; str += direct == HIGH ? " FWD" : " BWD"; return str; } void runCommand(int cmd) { switch (cmd) { case kCodeUp: op_m1_run = HIGH; op_m1_direct = HIGH; break; case kCodeDown: op_m1_run = HIGH; op_m1_direct = LOW; break; case kCodeLeft: op_m2_run = HIGH; op_m2_direct = HIGH; break; case kCodeRight: op_m2_run = HIGH; op_m2_direct = LOW; break; case kCodeGrab: break; case kCodeRelease: break; case kRotateL: break; case kRotateR: break; case kCodeBtnUp: op_m1_run = LOW; op_m2_run = LOW; break; } digitalWrite(moter1, op_m1_run); digitalWrite(moter2, op_m2_run); digitalWrite(moter1_ctrl, op_m1_direct); digitalWrite(moter2_ctrl, op_m2_direct); } void display() { lcd.clear(); lcd.print(formatMotorStatus("M1", op_m1_run, op_m1_direct)); lcd.setCursor(0, 1); lcd.print(formatMotorStatus("M2", op_m2_run, op_m2_direct)); } void commandLoop(const String& line) { int start = 0; int end = 2; while (end <= line.length()) { // Split into each command char buf[4] = {0,}; line.substring(start, end).toCharArray(buf, 4); int cmd = atoi(buf); // Avoid command duplicated if (cmd != last_cmd) { Serial.print(cmd); runCommand(cmd); display(); } last_cmd = cmd; start += 2; end += 2; } } void loop() { String line; if (!btSerial.available()) { return; } line += btSerial.read(); commandLoop(line); delay(50); }
아래는 LCD 사용로직을 제거한 코드
#include <SoftwareSerial.h> SoftwareSerial btSerial(11,12); // RX, TX of bluetooth const int moter1_ctrl = 2; const int moter1 = 3; const int moter2_ctrl = 4; const int moter2 = 5; const int kCodeUp = 56; const int kCodeDown = 50; const int kCodeLeft = 52; const int kCodeRight = 54; const int kCodeGrab = 67; const int kCodeRelease = 68; const int kRotateL = 69; const int kRotateR = 70; const int kCodeBtnUp = 48; int op_m1_run = LOW; int op_m2_run = LOW; int op_m1_direct = HIGH; int op_m2_direct = HIGH; int last_cmd = 0; void setup() { Serial.begin(9600); btSerial.begin(9600); pinMode(moter1, OUTPUT); pinMode(moter1_ctrl, OUTPUT); pinMode(moter2, OUTPUT); pinMode(moter2_ctrl, OUTPUT); digitalWrite(moter1_ctrl, HIGH); digitalWrite(moter2_ctrl, HIGH); } void runCommand(int cmd) { switch (cmd) { case kCodeUp: op_m1_run = HIGH; op_m1_direct = HIGH; break; case kCodeDown: op_m1_run = HIGH; op_m1_direct = LOW; break; case kCodeLeft: op_m2_run = HIGH; op_m2_direct = HIGH; break; case kCodeRight: op_m2_run = HIGH; op_m2_direct = LOW; break; case kCodeGrab: break; case kCodeRelease: break; case kRotateL: break; case kRotateR: break; case kCodeBtnUp: op_m1_run = LOW; op_m2_run = LOW; break; } digitalWrite(moter1, op_m1_run); digitalWrite(moter2, op_m2_run); digitalWrite(moter1_ctrl, op_m1_direct); digitalWrite(moter2_ctrl, op_m2_direct); } void commandLoop(const String& line) { int start = 0; int end = 2; while (end <= line.length()) { // Split into each command char buf[4] = {0,}; line.substring(start, end).toCharArray(buf, 4); int cmd = atoi(buf); // Avoid command duplicated if (cmd != last_cmd) { Serial.print(cmd); runCommand(cmd); } last_cmd = cmd; start += 2; end += 2; } } void loop() { String line; if (!btSerial.available()) { return; } line += btSerial.read(); commandLoop(line); delay(50); }
자 일단 처음 목표했던건 만들었고
다음은… 여기다 캠을 달아볼까?? ㅋㅋ
// 수정: 2015.05.30
두번째의 LCD가 제거된 코드에 블루투스 초기화 로직이 빠져있었다..ㄷㄷㄷ
첫번째 코드에는 있는 내용인데 LCD관련 코드 제거하면서 빠졌나보다.
그덕에 괜한 사람들이 삽질을…;