본문 바로가기
Project/DRSSTC

아두이노 프로젝트- Tesla coil interrupter interface

by No Brainer 2022. 2. 19.

 /*

  * 핀배열

  * 적외선센서 출력 - A0

  * 서보모터 데이터 -7

  * 초음파 출력(trig)-5

  * 초음파 입력(echo)-4

  * 감지여부 확인 출력-6

  * 블루투스 tx핀 - 2

  * 블루투스 rx핀 - 3

  */

//공격용 인터럽트 관련

 

int cwThresh = 1020;         // Sets CW Mode threshold (cwThresh/1023 *5)= Volts.

int minFreq = 2;            // Minimum Frequency in Hz.

int fDiv = 2;               // Frequency range divider. maxFreq = fDiv/1024.

 

 

int vpw;

int vbps;

int ontime;

int offtime;

int period;

int freq;

float duty;

 

int outPin = 9;

int bpsPin = A3;

int pwPin = A2;

 

//블루투스 통신 관련

#include <SoftwareSerial.h>

int T = 2;// 블루투스 모듈의 TXD 핀과 연결된 2번을 T 라는 변수로,

int R = 3;// 블루투스 모듈의 RXD 핀과 연결된 3번을 R 이라는 변수로 선언한다.

char data;

SoftwareSerial my_blue(T, R);

 

//서보관련 

#include <Servo.h>

Servo myservo;

int pos = 0;

int ref_val = 700;//기준거리, 단위 mm. 50cm이내 detection

int delay_num = 5;//원래 1이었음

unsigned int angle = 1;//원래 2였음

 

//적외선 거리측정 관련

#define SIZE 3

int buffer[SIZE];

float sum;

int sensorValue;

float EMA_a = 0.4;      

int EMA_S_pre = 0;    

int EMA_S=0;    

float volts;

 float ir_distance ;

 

//초음파 거리측정 관련

unsigned long duration;

float distance;

 

float dist;//최종 거리값

 

//딜레이 스위치 관련

unsigned long ref_time = 500000;

int cnt= 10;

//setup 관련

int trig= 5;

int echo= 4;

int attack_detection_pre= 6;

 

 

void setup()

{

 pinMode( trig, OUTPUT );  // HC-SR04의 Trig출력 5번

 pinMode( echo, INPUT );   // HC-SR04의 Echo입력 4번

 digitalWrite( trig, LOW );// Trig로 LOW신호 출력

 delay(10);             // 10ms 딜레이

 //Serial.begin(9600);    // 9,600 시리얼통신시작

 my_blue.begin(9600);

 

 ///////////////

 myservo.attach(7);

 

 ////////////////

 pinMode( attack_detection_pre, OUTPUT);//6번핀. 감지되면 출력됨.

 ////////////////

 pinMode(8, OUTPUT);//연주모드일때 high 공격모드일때 low

/////////////////

 pinMode(outPin, OUTPUT);//9번

 pinMode(bpsPin, INPUT);//A3

 pinMode(pwPin, INPUT);//A2

 

 

}

//////////////////////////////////////////////

 

void interrupter_for_attack (void)

{

    vpw = analogRead(pwPin);         // read pw voltage

  vbps = analogRead(bpsPin);       // read bps voltage

 

  vpw=250;

  vbps=40;

  

  /*if (vbps >= cwThresh) //1020  / CW mode threshold

  {          

    digitalWrite(outPin, HIGH);

    delayMicroseconds(100);

  }*/

  

    if (vbps >= cwThresh) //VBPS가 cwThresh를 넘어서면 출력을 DISABLE함.

  {          

    digitalWrite(outPin, LOW);

    delayMicroseconds(100);

  }

  

  else //일반적인 경우.

  {

    freq = 1 + ((vbps + fDiv) / fDiv);// Frequency range divider.   fDiv는 2이다. 

    

    if (freq < minFreq) //최소 주파수 설정

    {

      freq = minFreq;

    }

 

    

    if (vpw < 52) //최소 펄스폭 설정

    {               

      vpw = 52;

    }

 

    

    duty = vpw;

    duty = duty / 2046;//듀티사이클 산출

 

    

    if (freq <= 33) 

    {

      if (freq > 25 && duty <= 0.035) //주파수는 25~33, 듀티는 0.035 이하.

      {

        period = 1000 / freq;//주기 산출

        float onFloat = duty * period;

        float offFloat = period - onFloat;

        offtime = offFloat;

        int onshort = 1000 * onFloat;

        digitalWrite(outPin, HIGH);

        delayMicroseconds(onshort);

        digitalWrite(outPin, LOW);

        delay(offtime);

      }

      else

      {

        period = 1000 / freq;

        ontime = duty * period;

        offtime = period - ontime;

        digitalWrite(outPin, HIGH);

        delay(ontime);

        digitalWrite(outPin, LOW);

        delay(offtime);

      }

    }

 

 

 

    

    if (freq >= 34 && freq <= 54) //주파수가 34~54. this range glitches badly, PWM 고정시킴.

    {  

      duty = 0.2;

      period = 1000000 / freq;

      ontime = duty * period;

      offtime = period - ontime;

      digitalWrite(outPin, HIGH);

      delayMicroseconds(ontime);

      digitalWrite(outPin, LOW);

      delayMicroseconds(offtime);

    }

 

    

    

    if (freq >= 55) //주파수가 55이상일 경우

    {

      period = 1000000 / freq;

      ontime = duty * period;

      offtime = period - ontime;

      digitalWrite(outPin, HIGH);

      delayMicroseconds(ontime);

      digitalWrite(outPin, LOW);

      delayMicroseconds(offtime);

    }

  }

}

 

 

float ultra_sonic (void)

{

  digitalWrite(trig, LOW);

  digitalWrite(echo, LOW);

  delayMicroseconds(2);

  digitalWrite(trig, HIGH);

  delayMicroseconds(10);

  digitalWrite(trig, LOW);

 

  duration = pulseIn(echo, HIGH);

  distance = duration / 29.0 / 20.0*100.0;

 

  return distance;

  

}

 

 

 

void caculating_dist (void)

{

  //복합필터 적용한 적외선 거리측정

  sensorValue = analogRead(0);    //아날로그 센서값(적외선 센서값) 리딩        

                  

  EMA_S_pre = (EMA_a*sensorValue) + ((1-EMA_a)*EMA_S_pre);   //로우패스 필터 필터링 수식을 통해 필터링 된 센서값 도출(EMA_S_pre)

  //이동평균 필터 적용////////////////////////////

  sum-=buffer[0];

  for(int i =0; i<SIZE-1 ; i++)

  {

    buffer[i]=buffer[i+1];

  }

  buffer[SIZE-1]=EMA_S_pre;

  sum+=buffer[SIZE-1];

  EMA_S=sum/SIZE+2;//이동평균필터를 통해 최종 필터링한 센서값 도출(EMA_S)

  ////////////////////////////////

 

  volts=(EMA_S) * 5.0/ 1023.0;

  ir_distance = 604.95* pow(volts, -1.1904);//필터링된 거리값 도출

 

  if(ir_distance<200)

  {

    dist=ultra_sonic();//20cm이내에서 dist 값은 초음파센서 측정을 통해 얻어짐

   

  }

  else

  {

    dist=ir_distance;//20cm밖에서의 dist값은 적외선측정을 통해 얻어짐.

  }

//Serial.println(dist);

}

 

 

 

///////////////////////////////////////////////

void loop()

{

 if(my_blue.available())//만일 블루투스에서 뭔가 받으면, 그 값을 data에 저장

  {

    data = (char)my_blue.read();

  }

 

  

///////////////////////////////////////////////////////////////////////////////////////

  while(data=='a')//공격모드인 경우, 모터 회전, 센서 코드 및 인터럽트 코드 반복문 실행

  {

    digitalWrite(8,LOW);//8번핀에 LOW. LOW가 공격용.

 

/////////////////////////////    

for(pos = 0; pos < 180; pos += angle)

{

    myservo.write(pos);//일단 움직인다

    delay(delay_num); 

    caculating_dist ();//dist값 갱신하고 이 값을 바로 아래 while문에서 검사

    

  while(dist<ref_val)//거리 1미터이내면 진입, 아니면 while반복문 탈출

  { 

    digitalWrite(6,HIGH);//1미터 이내일 경우, 6번핀에 high주고

    interrupter_for_attack ();//인터럽트 신호 1회 발생

    caculating_dist ();

     

    if(dist>=ref_val)//1미터 밖일 경우, 6번핀 끄고 반복 종료

    {digitalWrite(6,LOW);

      break;

    }

    

   if(my_blue.available())//뭔가 받았을때 그게 m이면 while반복문 탈출

  {

    data = (char)my_blue.read();

  }

  if(data=='m')

  {

  digitalWrite(6,LOW);

  break;

  }

 

  }

 

      if(my_blue.available())//뭔가 받으면

  {

    data = (char)my_blue.read();

  }

  if(data=='m')

  break;

 

}//for문 1번 종료

 

 

for(pos = 180; pos>=1;pos-=angle)

{

    myservo.write(pos);

    delay(delay_num); //일단 움직인다

    caculating_dist ();//dist값 갱신하고 이 값을 바로 아래 while문에서 검사

    

    

  while(dist<ref_val)//거리 1미터이내면 진입, 아니면 while반복문 탈출

  { 

    digitalWrite(6,HIGH);  

    interrupter_for_attack ();//인터럽트 신호 1회 발생    

    caculating_dist ();

   

    

    if(dist>=ref_val)//조건 불부합시.

    {digitalWrite(6,LOW);

      break;

    }

 

    

    if(my_blue.available())//뭔가 받으면

  {

    data = (char)my_blue.read();

  }

  if(data=='m')

  {

  digitalWrite(6,LOW);

  break;

  }

 

   }   

    if(my_blue.available())//뭔가 받으면

  {

    data = (char)my_blue.read();

  }

  if(data=='m')

  break;

   

}

////////////////////////////////

 

 if(my_blue.available())//뭔가 받으면

  {

    data = (char)my_blue.read();

  }

  if(data=='m')

  break;

  

  }//data 가 a일 경우.

 

  ////////////////////////////////////////////////////////////////////////////

 

  while(data=='m')//연주모드일경우.

  {

   digitalWrite(8,HIGH);//8번에 HIGH. HIGH가 연주모드를 설정함.

 

 

 

 

    

  if(my_blue.available())//뭔가 받으면

  {

    data = (char)my_blue.read();

  }

  if(data=='a')

  break;

  }

  /////////////////////////////////////////////////////////////////////////////

 

  }//메인 루프문