2015년 2월 2일 월요일

아두이노 (센서로부터 입력받기)

무조건적으로 풀업 저항을 달고 시작할 것!!!!!
* 회로를 혼자 만들 수 있는 수준의 사람이라고 가정하고 써놓음

센서에서 정보를 제공하는 방법

1) 디지털 켜기/끄기
 ex) tilt seneor , motion sensor

2) 아날로그
 감지된 값에 비려하는 전압을 제공하는 센서도 있다.
 ex) 온도 ,조명 ,동작, 진도, 소리
analogRead 명령어를 사용한다.

3) 펄스 폭
 거리값에 비례하는 펄스 지속 시간을 사용하여 데이터를 제공한다.
 ex) PING))
pulseIn 명령을 사용하여 펄스의 지속 시간을 측정한다.

4) 시리얼
시리얼 프로토콜을 사용하여 값을 제공한다.
ex) GPS

5) 동기 프로토콜 : I2C와 SPI
이 장이 아닌 또다른 장에서 자세히 다룰 것임

주의점:
1) 센서를 사용하기 전에 센서의 데이터시트를 잘 참조해라
2) 센서의 출력값을 일반인들이 알아볼 수 있는 단위로 변경하는 코드를 짜넣어라
3) 원하는 신호와 주위의 잡음을 분리할 수 있어야 한다.


 흔들림 감지하기(디지털로 신호를 주는 센서 처리 방법)
/*tilt sketch*/
const int tiltSensorPin = 2;   //틸트 센서가 연결된 핀
const int firstLEDPin = 11;   // LED 핀 중 하나
const int secondLEDPin = 12;    //또 하나의 LED 핀

void setup()
{
  pinMode(tiltSensorPin,INPUT);   // 2번 핀을 읽는다
  pinMode(tiltSensorPin,HIGH);     //풀업 저항을 사용

  pinMode(firstLEDPin, OUTPUT);   // 11 핀을 제어한다.
  pinMode(secondLEDPin,OUTPUT);   // 12 핀을 제어한다.
}

void loop()
{
  if(digitalRead(tiltSensorPin)) {   //핀이 high인지 검사한다.
    digitalWrite(firstLEDPin,HIGH);   //high라면 firstLED를 켠다.
    digitalWrite(secondLEDPin,LOW);   //secondLED를 켠다
  }else{
    digitalWrite(firstLEDPin,LOW);   //반대로 수행한다.
    digitalWrite(secondLEDPin,HIGH);
  }
}
=> 틸트 센서의 기울어진 방향에 따라 LED 중 하나가 켜짐


/* shaken sketch*/

const int tiltSensorPin = 2;  //틸트 센서가 연결된 핀
const int ledPin = 13;   //led가 연결된 핀
int tiltSensorPreviousValue = 0;   //틸트센서의 과거값
int tiltSensorCurrentValue = 0;   //틸트센서의 현재값
long lastTimeMoved = 0;   /마지막으로 흔들렸던 시간
int shakeTime = 50;   //흔들림의 기준

void setup()
{
  pinMode(tiltSensorPin,INPUT);  // 2번 핀을 읽는다
  digitalWrite(tiltSensorPin,HIGH);   //풀업 저항 사용
  pinMode(ledPin,OUTPUT);   // 13 핀을 제어한다.
}
void loop()
{
  tiltSensorCurrentValue = digitalRead(tiltSensorPin);  // 2번 핀의 값을 현재값에 대입한다
  if(tiltSensorPreviousValue != tiltSensorCurrentValue) {  //과거값과 현재값이 같지 않으면
    lastTimeMoved = millis();  
  //millis: 프로그램이 시작된 후의 시간을 밀리세컨드 단위로 리턴한다.
    tiltSensorPreviousValue = tiltSensorCurrentValue;    //현재값을 과거값에 대입
  }

  if(millis() - lastTimeMoved < shakeTime) {  // 흔들렸으면
    digitalWrite(ledPin,HIGH);
  }
  else {   //흔들리지 않았으면
    digitalWrite(ledPin,LOW);
  }
}

흔들림을 판단하는 메커니즘

------------------------------------------------------------------------->
millis

               l             l                           l        l                l                 l          l       >
lastTimeMoved

               --------  ----------------  ----   --------   ----------  ------
millis - lasttimeMoved =>이게 50 millisecond 이되지 않으면 흔들린 것으로 간주


  조명 감지하기( 아날로그 신호를 주는 센서들 처리 방법)
/*light sensor*/
const int ledPin = 13;
const int sensorPin =0;

void setup()
{
  pinMode(ledPin,OUTPUT);
}

void loop()
{
  int rate = analogRead(sensorPin); // 0 ~ 1023 사이의 값으로 나온다.
  digitalWrite(ledPin, HIGH);
  delay(rate);
  digitalWrite(ledPin,LOW);
  delay(rate);
}


거리 측정하기(펄스 폭 신호를 주는 센서들 처리방법)

/*EZ1 Rangefinder Distance Sensor*/

const int sensorPin = 5;
const int ledPin = 13;

long value = 0;
int cm = 0;
int inches =0;

void setup()
{
  value = pulseIn(sensorPin, HIGH);
  cm = value / 58;                            //펄스 폭이 cm당 58마이크로다.
  inches = value / 147;                     //인치당 147마이크로초
  Serial.print(cm);
  Serial.print(',');
  Serial.println(inches);
  
  digitalWrite(ledPin, HIGH);
  delay(cm*10);                               //1센티미터당 지연 시간을 10밀리초 추가한다.
  digitalWrite(ledPin, LOW);
  delay(cm*10);
  
  delay(20);
}


정확한 거리 측정하기
/*infrared-ray_distance sketch*/

const int ledPin = 13;
const int sensorPin  = 0;
const long referenceMv = 5000;    //곱하기 연산 시 오버플로우를 방지하기 위한 long형 정수

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
}

void loop()
{
  int val = analogRead(sensorPin);
  int mV = (val * referenceMv) / 1023;
  
  Serial.print(mV);
  Serial.print(",");
 int cm = getDistance(mV);
 Serial.println(cm);

 digitalWrite(ledPin,HIGH);
 delay(cm * 10);
 digitalWrite(ledPin,LOW);
 delay(cm * 10);

 delay(100);
}

const int TABLE_ENTRIES = 12;
const int INTERVAL = 250;

static int distance[TABLE_ENTRIES] = {150,140,130,100,60,50,40,35,30,25,20,15};

int getDistance(int mV)
{
 if(mV > INTERVAL * TABLE_ENTRIES-1)   // 1)
return distance[TABLE_ENTRIES -1];
else
{
  int index = mV / INTERVAL;   // 2)

  float frac = (mV % 250) / (float)INTERVAL;   // 3)
  return distance[index] + ((distance[index]) * (frac*100));
}
}
/* IR 센서의 출력은 거리에 비례하지 않는다
 * 이 때 적용되는 기술: 보간(interpolating)
 * 전압을 거리로 변환하는 작업을 수행하는 함수
 *  int getDistance(int mv)
 * 1) 값이 테이블에 지정된 범위 내에 있는 지 검사한다. 값이 범위 내에 없으면 가장 짧은    * 유효 거리가 리턴된다.
 * 2) 값이 테이블 범위 내에 있으면 정수 나누기 연산을 통해 판독값보다 낮으면서 가장 가    * 까운 항목이 계산된다.
 * 3) 판독값이 두 항목 사이에 있을 경우에는 모듈로 연산자를 사용해서 소수 값이 계산된다


소리 감지하기
/* microphone sketch*/
const int ledPin =13;              // 핀 13의 LED가 켜진다.
const int middleValue = 512;   // 아날로그 값 범위의 중간값
const int numberOfSamples = 128;   // 한 번에 읽어올 판독값의 개수

int sample;                   // 마이크로폰에서 읽어온 값
long signal;                  // DC 오프셋을 제거한 이후의 판독값
long averageReading;   // 해당 루프 동안 읽어온 값의 평균

long runningAverage = 0;   // 계산된 값의 실행 평균
const int averagedOver = 16;   // 새 값이 실행 평균에 영향을 미치는 속도
                                            // 숫자가 클수록 느려진다.

const int threshold = 400;     // 조명레벨

void setup() {
  pinMode(ledPin,OUTPUT);
  Serial.begin(9600);
}
void loop() {
  long sumOfSquares = 0;
  for (int i = 0; i < numberOfSamples; i++) {   // 많은 값을 읽어와서 평균을 구한다.
    sample = analogRead(0);                        // 값을 읽어온다
    signal = (sample - middleValue);             // 오프셋을 적용한다.
    signal *= signal;                                     // 양수가 되도록 값을 제곱한다.
    sumOfSquares += signal;                       // 합계를 추가한다.
  }
  averageReading = sumOfSquares/numberOfSamples;   //실행 평균을 계산한다.
  runningAverage=(((averagedOver-1)*runningAverage)+averageReading)/averagedOver;
  
  if(runningAverage>threshold) {   // 평균이 임계값보다 큰가?
    digitalWrite(ledPin,HIGH);       // 그렇다면 LED를 켠다.
  }else{
    digitalWrite(ledPin,LOW);       // 그렇지 않다면 LED를 끈다.
  }
  Serial.println(runningAverage);   // 값을 확인하기 위해 인쇄한다.

}


RFID 태그 판독하기
/*RFID sketch*/
const int startByte = 10;    // 각 태그 앞에 아스키 줄 바꿈 문자를 사용한다.
const int endByte = 13;     // 각 태그 끝에 아스키 캐리지 리턴 문자를 사용한다.
const int tagLength = 10;   // 태그의 자릿수
const int totalLength = tagLength + 2;   // 태그 길이 + 시작 및 종료 바이트
char tag[tagLength + 1];     // 태그와 종료 널 포함

int bytesread = 0;

void setup()
{
  Serial.print(2400);        // RFID 판독기의 전송 속도로 설정한다.
  pinMode(2,OUTPUT);   // RFID ENABLE 핀에 연결된다. 
  digitalWrite(2,LOW);    // RFID 판독기를 실행한다.
}

void loop()
{
  if(Serial.available() >= totalLength)   // 충분한 데이터가 있는지 검사한다.
  {
    if(Serial.read() == startByte)
    {
      bytesread = 0;   //태그의 시작이므로 count를 0으로 재설정한다.
      while(bytesread < tagLength)   // 10자리 코드를 읽는다.
      {
        int val = Serial.read();
        if((val == startByte)||(val == endByte))  // 코드의 끝을 검사한다.
        break;
        tag[bytesread] = val;
        bytesread = bytesread + 1;   // 다음 자릿수의 코드를 읽기 위해 준비한다.
      }
      if(Serial.read() == endByte)   // 올바른 종료 문자인지 검사한다.
      {
        tag[bytesread] = 0;   // 문자열을 종료한다.
        Serial.print("RFID tag is: ");
        Serial.println(tag);
      }
    }
  }

}


로터리 이동 추적하기
/*rotary-movement sensor*/
const int encoderPinA = 4;   // 인코더가 회전하고 있는 지의 여부
const int encoderPinB = 2;   // 인코더가 회전하고 있는 방향
const int encoderStepsPerRevolution = 16;   // 회전당 단계수
int angle = 0;

int val;

int encoderPos = 0;
boolean encoderALast = LOW;   // 이전 핀의 상태를 기억한다.

void setup()
{
  pinMode(encoderPinA,INPUT);
  pinMode(encoderPinB,INPUT);
  digitalWrite(encoderPinA, HIGH);
  digitalWrite(encoderPinB, HIGH);
  Serial.begin(9600);
}

void loop()
{
  boolean encoderA = digitalRead(encoderPinA);  // 인코더 핀 하나를 읽는다.
  
  if ((encoderALast == HIGH) && (encoderPinA == LOW));  
  {
    if(digitalRead(encoderPinB) == LOW)
    {
      encoderPos--;
    }
    else
   {
    encoderPos++;
   }
  angle=(encoderPos % encoderStepsPerRevolution)*360/encoderStepsPerRevolution; 
   Serial.print(encoderPos);
   Serial.print(" ");
   Serial.println(angle);
  }
  encoderALast = encoderA;
}

  

댓글 없음:

댓글 쓰기