2017. 10. 15. 17:27ㆍArduino
이전에 핸들에 500mm softpot membrane potentiometer를 붙여서, 핸들을 잡은 구간을 인식을 해서 LED strip으로 빛을 출력했다.
이제 부품 관련 기능을 모두 확인을 완료했으니, 우리 팀이 구현하고자 하는 제품을 만들기만 하면 된다.
우리 팀이 만드는 프로젝트는 청각장애인을 위한 내비게이션 시스템이다.
안드로이드 앱에서 통신을 주면 핸들에서 해당하는 신호에 대한 LED 및 진동을 출력을 해주는 것이다.
기본 가죽 핸들 커버(인터넷에서 5000원이면 살 수 있는) 위에 Softpot을 올리고, 그 위에 LED strip을 올린다.
Softpot이랑 LED strip을 핸들 가운데 부분에 쌓아올린 후, 핸들 뒷편에는 진동 13개를 하나씩 일정한 간격을 두고 붙인다.
그리고 그 위에 가죽이랑 불투명 천 재질로 된 커버를 다시 씌워서, LED랑 진동이 울릴 수 있는 핸들커버로 만드는 것이다.
이런 부품들이 적층된 구조라서 쉽게 구현을 할 수 있지만, 납땜만 좀 시간이 걸렸다,,,
아래 하드웨어 단면도를 보면 한 눈에 어떻게 만들어졌는지 알 수 있다.
------------------------------------------------------------------------------------------------------------------------------------------
전체 하드웨어 회로도는 이렇게 구성이 된다.
연결된 핀을 표로 정리하면 아래와 같다.
핸들 후면부에 진동 모듈 13개가 들어가는 위치는 이렇게 되고, 손을 잡은 위치에 따라 구간마다 2개 및 3개의 진동을 울리게 해서 진동을 감지할 수 있게 했다.
# 아두이노 나노 보드 판에 납땜을 해서 보면 아래와 같이 보여지는데, 여기서 하드웨어 단가를 낮추려고 아두이노 나노 호환되는 제품으로 보드를 사용하다가 USB 드라이버를 인식을 하지 못한다는 문제를 발견해서, 아두이노 나노 정품 보드판을 사용하는 것으로 변경하였다.
사실 아두이노 나노 호환 드라이버를 설치를 해서 USB 잭을 인식시킬 수 있으나, 그 과정에서 중간에 오류가 나는 부분이 많아서 아두이노 나노 정품 보드판을 사용했다.
업로드 도중에 컴퓨터 자체가 다운되는 일도 빈번해서 정확한 해결방법을 못찾아서 정품을 사용하게 됨.
------------------------------------------------------------------------------------------------------------------------------------------
납땜까지 완료된 하드웨어 사진을 보면 아래와 같다.
납땜형 브레드보드 / NS-PB-P-02 를 사용한 이유는, 이전까지 아두이노 UNO로 부품 테스트를 할 때 사용한 브레드보드와 같은 기능을 하는 브레드 보드이기 때문에 사용했다. 기존의 브레드보드처럼 양극 음극이 서로 이어져 있고 번호마다의 선로가 이어져 있어서 쉽게 사용할 수 있고 납땜만 해주면 된다.
진동 모듈이 13개가 들어가서 점퍼선이 많이 사용됐다.
전원은 리튬 이온 배터리 원통형 3.7v 두 개를 사용해서 전력을 공급했다.
기존의 아두이노 UNO로 사용을 할 때는 USB 잭을 통해서 전원을 공급했기 때문에 그대로 이어주기만 하면 됐는데, 외부 전력을 사용할 시 VIN에 외부 전지 +극을 연결하고 -극은 -쪽에 연결을 해줘야한다.
또 차량 내부에서도 충전을 가능하게 하기 위해서 하드웨어 본체 3D 프린팅도 선을 연결할 수 있게 구멍이 난 형태로 제작을 하게됐다.
가죽으로 핸들 커버를 씌웠고, 그 중간에 반투명 재질 천을 배치시켜서 LED 빛이 출력되는 것을 알 수 있게 했다.
LED 빛이 너무 직접적으로 눈에 들어오게 되면 눈이 부실 수 있는데, 반투명 재질 천이 있어서 눈이 부시지 않게 LED 빛을 볼 수 있다.
기존의 핸들 커버에 하드웨어 모듈들을 두고 다시 그 위에 손수 제작한 가죽 및 반투명 천 커버를 씌운 것이라서
기존 커버와 제작한 커버를 손으로 꿰매주었다.
3D 프린팅 커버에 넣었을 때의 하드웨어 본체 모습이다.
아래와 같은 코드로 안드로이드에서 신호를 보내주면 어떤 신호인지 구분해서 핸들에서 출력을 하게 된다.
[100_12.] 이런 식으로 애플리케이션에서 신호를 보내게 되면,
아두이노에서 띄어쓰기를 구분해서 거리 정보를 받아오고(100)
좌회전(12)이라는 신호를 받아서 출력한다.
(.)은 문자열 신호의 끝부분이라고 인식을 해서 문자열의 종료를 인식한다.
나머지 코드들은 앞서 부품을 확인하는 과정에서 사용한 코드들이 종합된 것이다.
#include <SoftwareSerial.h> #include <Adafruit_NeoPixel.h> #define PIN 6 #define LEFTTOUCH 1 #define RIGHTTOUCH 2 int softpotLeft; int softpotRight; int blueRx = 2; int blueTx = 3; int latchPin = 8; int clockPin = 12; int dataPin = 11; String meter = ""; String turnType = ""; boolean isTurnType = false; boolean complete = false; char inChar; byte buffer[1024]; byte data; byte touchData[] = { B00000000, B00000000}; //좌측6개89abcd00, 우측7개12345670 //총 13개 진동모 SoftwareSerial mySerial(blueRx, blueTx); Adafruit_NeoPixel strip = Adafruit_NeoPixel(35, PIN, NEO_RGBW + NEO_KHZ800); void SetVibration(int mode,int softpotReading) { if(mode == RIGHTTOUCH) // 오른쪽터치 { if(softpotReading >= 0 && softpotReading < 483) { touchData[1] = B11000000; } else if(softpotReading >= 483 && softpotReading < 630) { touchData[1] = B01100000; } else if(softpotReading >= 630 && softpotReading < 768) { touchData[1] = B00110000; } else if(softpotReading >= 768 && softpotReading < 902) { touchData[1] = B00011000; } else if(softpotReading >= 902 && softpotReading < 972) { touchData[1] = B00001100; } else if(softpotReading >= 972 && softpotReading < 1023) { touchData[1] = B00000110; } } else // 왼쪽터치 { if(softpotReading >= 0 && softpotReading < 508) { touchData[0] = B00001100; } else if(softpotReading >= 508 && softpotReading < 663) { touchData[0] = B00011000; } else if(softpotReading >= 663 && softpotReading < 788) { touchData[0] = B00110000; } else if(softpotReading >= 788 && softpotReading < 920) { touchData[0] = B01100000; } else if(softpotReading >= 920 && softpotReading < 985) { touchData[0] = B11000000; } else if(softpotReading >= 985 && softpotReading < 1023) { touchData[0] = B10000000; touchData[1] = touchData[1] | B00000010; } } } void ActivateVibration(int vibrationTime, int stopTime) { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, touchData[0]); shiftOut(dataPin, clockPin, LSBFIRST, touchData[1]); digitalWrite(latchPin, HIGH); delay(vibrationTime); StopVibration(); delay(stopTime); } void StopVibration() { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, B00000000); shiftOut(dataPin, clockPin, LSBFIRST, B00000000); digitalWrite(latchPin, HIGH); } void StartLight() { for(int i=0; i<35; i++) { strip.setPixelColor(i,155,0,0,0); strip.show(); delay(10); } for(int i=0; i<35; i++) { strip.setPixelColor(i,0,155,0,0); strip.show(); delay(10); } for(int i=0; i<35; i++) { strip.setPixelColor(i,0,0,155,0); strip.show(); delay(10); } for(int i=0; i<35; i++) { strip.setPixelColor(i,0,0,0,0); strip.show(); delay(10); } } void StopLight() { for(int i=0; i<35; i++) { strip.setPixelColor(i,0,0,0,0); strip.show(); } } void SetLight(String alert) { if(alert == "12") // 좌회전 { if(touchData[0] != B10000000) { touchData[1] = B00000000; } for(int i=0;i<18;i++) { strip.setPixelColor(i,255,0,0,0); strip.show(); } } else if(alert == "13") // 우회전 { touchData[0] = B00000000; for(int i=17;i<35;i++) { strip.setPixelColor(i,255,0,0,0); strip.show(); } } else if(alert == "14") // 유턴 { for(int i=0;i<9;i++) { strip.setPixelColor(i,255,0,0,0); strip.show(); } for(int i=26;i<35;i++) { strip.setPixelColor(i,255,0,0,0); strip.show(); } } else if(alert == "51" || alert == "11") // 직진 { for(int i=9;i<26;i++) { strip.setPixelColor(i,255,0,0,0); strip.show(); } } else if(alert == "100") // 위험감지 { for(int j=0;j<35;j++) { strip.setPixelColor(j,0,255,0,0); strip.show(); } } else if(alert == "101") // 과속알림 { for(int j=0;j<35;j++) { strip.setPixelColor(j,120,255,0,0); strip.show(); } } else if(alert == "102") // 예비 우회전 { for(int i=17;i<35;i++) { strip.setPixelColor(i,0,0,255,0); strip.show(); } } else if(alert == "103") // 예비 좌회전 { for(int i=0;i<18;i++) { strip.setPixelColor(i,0,0,255,0); strip.show(); } } else if(alert == "104") // 예비 직진 { for(int i=9;i<26;i++) { strip.setPixelColor(i,0,0,255,0); strip.show(); } } else if(alert == "105") // 예비 유턴 { for(int i=0;i<9;i++) { strip.setPixelColor(i,0,0,255,0); strip.show(); } for(int i=26;i<35;i++) { strip.setPixelColor(i,0,0,255,0); strip.show(); } } else { touchData[0] = B00000000; touchData[1] = B00000000; } } void setup() { mySerial.begin(9600); Serial.begin(9600); softpotLeft = analogRead(A0); softpotRight = analogRead(A1); pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); digitalWrite(A0, HIGH); digitalWrite(A1, HIGH); strip.begin(); strip.show(); //Initialize all pixels to 'off' StopVibration(); StartLight(); //하드웨어 처음 시작 알림 } void loop() { while(mySerial.available()) { inChar = (char)mySerial.read(); if(inChar == ' ') { isTurnType = true; } if(isTurnType) { if(inChar!=' '&&inChar!='.') { turnType += inChar; } if(inChar=='.') { isTurnType = false; Print(); handlear(meter, turnType); meter = ""; turnType = ""; } } else { meter += inChar; } } } void handlear(String meter, String turnType) { softpotLeft = analogRead(A0); softpotRight = analogRead(A1); delay(10); if (softpotRight < 1002 || softpotRight > 1007 || softpotLeft < 1002 || softpotLeft > 1007) { SetVibration(RIGHTTOUCH, softpotRight); SetVibration(LEFTTOUCH, softpotLeft); for(int l=0; l<5; l++) { SetLight(turnType); digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, touchData[0]); shiftOut(dataPin, clockPin, LSBFIRST, touchData[1]); digitalWrite(latchPin, HIGH); delay(500); StopVibration(); delay(100); } StopLight(); } } void Print() { Serial.println(meter); Serial.println("//"); Serial.println(turnType); }
'Arduino' 카테고리의 다른 글
아두이노 쉽게 시작하기 (0) | 2017.11.19 |
---|---|
[아두이노 커버 제작] 3D 프린팅, 3D printing (1) | 2017.10.15 |
[아두이노 부품] 블루투스 통신 (0) | 2017.10.15 |
[아두이노 부품] Arduino Adafruit NeoPixel control with Softpot 소프트팟으로 네오픽셀 조작 (0) | 2017.08.07 |
[아두이노 부품] Arduino Adafruit NeoPixel (0) | 2017.08.04 |