....

2023. 4. 27. 01:58·자율주행자동차/[2023] 1-fifth AA EV
728x90
#include <ros.h>
#include <std_msgs/Int8MultiArray.h>

/*=====ROS 통신을 위한 변수========*/
  ros::NodeHandle nh;
  std_msgs::Int8MultiArray msg;

  int8_t _speed=0; //0 - 10 km/h
  int8_t angle=0; //-30 - 30 degree
  int8_t gear=0;
/*==============================*/


/*=====하드웨어 제어를 위한 변수========*/
  int encoder_pot = A8;    // 조향모터 가변저항 및 조향모터의 PID제어를 위한 변수
  int val;
  int encoder_val;
  float kp = 0.1;
  float ki = 0.00000 ;
  float kd = 2.00;
  float Theta, Theta_d;
  int dt;
  unsigned long t;
  unsigned long t_prev = 0;
  int val_prev =0;
  float e, e_prev = 0, inte, inte_prev = 0;
  float Vmax = 24;
  float Vmin = -24;
  float V = 0.1;
  void SteerCon(); // 조향 모터의 PID제어 함수
  int St_M = 512;// 직진 조향값
  int steering_angle = 300;

  const byte interruptPinA = 2;  // 구동모터의 엔코더센서 핀번호
  const byte interruptPinB = 3;
  volatile long EncoderCount = 0; // 엔코더 값 변수

  const byte PWMPin = 12; // 조향 모터의 모터드라이브 PWM,DIR 핀번호
  const byte DirPin1 = 13;

  int PWMone = 10; // 구동 모터의 모터드라이브 PWM1,PWM2,DIR1,DIR2 핀번호
  int Dirone = 11;
  int PWMtwo = 8;
  int Dirtwo = 9;
  void mDrive(); // 구동 모터의 OPEN LOOP 제어 함수

  int Speed, Steer,HSteer=0,HSpeed=0; // 상위 제어기와 통신을 위한 변수
  byte State, ESTOP, Mode,HGear=0;
  byte ALIVE = 0;
  char SendMessage[17];

  int Thro,Aux,Gear,ALIE,T,A,G,AL; // 조종기를 위한 변수
  void controller(); // 조종기 통신 함수
/*==============================*/

/*=====ROS 통신을 위한 함수========*/
void msgCallback(const std_msgs::Int8MultiArray& msg) {
  _speed=msg.data[0];
  angle=msg.data[1];
  gear=msg.data[2];
}

ros::Subscriber<std_msgs::Int8MultiArray> sub("SpeedAngleGear", &msgCallback);
/*==============================*/

void setup(){
  /*======ROS 통신========*/
  nh.initNode();
  nh.subscribe(sub);
  /*=====================*/
  pinMode(DirPin1, OUTPUT); // 조향 모터
  pinMode(PWMone,OUTPUT);
  pinMode(Dirone,OUTPUT); // 구동 모터
  pinMode(PWMtwo,OUTPUT);
  pinMode(Dirone,OUTPUT);
  pinMode(interruptPinA, INPUT_PULLUP); // 엔코더 핀
  pinMode(interruptPinB, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPinA), ISR_EncoderA, CHANGE); // 엔코더 값을 읽기 위한 인터럽트 서비스 루틴
  attachInterrupt(digitalPinToInterrupt(interruptPinB), ISR_EncoderB, CHANGE); 

  //State=1;
}

void loop(){
  /*=====for Debugging=======*/
  char ch[20]={0};
  if(angle>0){
    ch[0]=angle/10+48;
    ch[1]=angle%10+48;
  }
  else{
    ch[0]='-';
    ch[1]=-1*angle/10+48;
    ch[2]=-1*angle%10+48;
  }
  nh.loginfo(ch);
  /*============================*/
  HSpeed=_speed;
  HSteer=angle;
  HGear=gear;

  HSpeed = map(HSpeed, 0, 10, 0, 255);
  HSteer = map(HSteer, -30, 30, 0, 1000);
  Mdrive(HSpeed,HGear);    //SPEED값 제어
  SteerCon(HSteer);    //STEER값 제어

  nh.spinOnce();
  delay(1);
}

void SteerCon(float Q) { // 조향모터의 제어를 위한 함수, Q = 조향 목표값  
    val = Q;                          
    if(val > St_M + steering_angle){  // 조향 최대값 제한
      val = St_M + steering_angle;
    }
    else if(val < St_M - steering_angle){ // 조향 최소값 제한
      val = St_M - steering_angle;
    }
    encoder_val = analogRead(encoder_pot);               // Read V_out from Feedback Pot
    t = millis();

    dt = (t - t_prev);                                  // Time step
    Theta = val;                                        // Theta= Actual Angular Position of the Motor
    Theta_d = encoder_val;                              // Theta_d= Desired Angular Position of the Motor

    e = Theta_d - Theta;                                // Error -> 목표 값에서 현재 값을 빼야하는 거 아닌가?
    inte = inte_prev + (dt * (e + e_prev) / 2);         // Integration of Error
    V = kp * e + ki * inte + (kd * (e - e_prev) / dt) ; // Controlling Function

    if (V > Vmax) {
      V = Vmax;
      inte = inte_prev;
    }
    if (V < Vmin) {
      V = Vmin;
      inte = inte_prev;
      val_prev= val;
    }
    int PWMval = int(255 * abs(V) / Vmax);
    if (PWMval > 200) {
      PWMval = 200;
    }
    if (V > 0.5) {
      digitalWrite(DirPin1, HIGH);
      analogWrite(PWMPin, PWMval);
    }
    else if (V < -0.5) {
      digitalWrite(DirPin1, LOW);
      analogWrite(PWMPin, PWMval);
    }
    else {
      digitalWrite(DirPin1, LOW);
      analogWrite(PWMPin, 0);
    }
    t_prev = t;
    inte_prev = inte;
    e_prev = e;
} 

void Mdrive(int q,int w){ //구동모터의 제어를 위한 함수, q = Speed, w = 정,역방향 지정
  // 정방향
  if(w == 0){
    digitalWrite(Dirtwo,1);
    analogWrite(PWMtwo,q);
    digitalWrite(Dirone,0);
    analogWrite(PWMone,q);
  }

  // 역방향
  else if(w == 2){
    digitalWrite(Dirtwo,0);
    analogWrite(PWMtwo,q);
   digitalWrite(Dirone,1);
   analogWrite(PWMone,q);
  }

  // e-stop
  else if(w == 1){
    digitalWrite(Dirtwo,0);
    analogWrite(PWMtwo,0);
    digitalWrite(Dirone,0);
    analogWrite(PWMone,0);
  }
}

void ISR_EncoderA() { // 엔코더 값을 저장하기 위한 내부 인터럽트 서비스 함수
  bool PinB = digitalRead(interruptPinB);
  bool PinA = digitalRead(interruptPinA);

  if (PinB == LOW) {
    if (PinA == HIGH) {
      EncoderCount++;
    }
    else {
      EncoderCount--;
    }
  }

  else {
    if (PinA == HIGH) {
      EncoderCount--;
    }
    else {
      EncoderCount++;
    }
  }
}
void ISR_EncoderB() { // 엔코더 값을 저장하기 위한 내부 인터럽트 서비스 함수
  bool PinB = digitalRead(interruptPinA);
  bool PinA = digitalRead(interruptPinB);

  if (PinA == LOW) {
    if (PinB == HIGH) {
      EncoderCount--;
    }
    else {
      EncoderCount++;
    }
  }

  else {
    if (PinB == HIGH) {
      EncoderCount++;
    }
    else {
      EncoderCount--;
    }
  }
}

void controller() {
    ALIE = pulseIn(A0, HIGH, 50000);  //CH1,좌우 //ALIE는 STEER값임.
    // 아날로그3번 핀의 pwm입력신호가 LOW로 바뀐 순간부터 HIGH로 바뀌는 순간까지의 경과시간을 마이크로초 단위로 Rudd변수에 저장.
    // 만약, 50ms시간동안 펄스의 변화가 없다면, 0값이 Rudd변수에 저장된다.
    Thro = pulseIn(A1, HIGH, 50000);  //CH2, 앞뒤  
    // 아날로그5번 핀의 pwm입력신호가 LOW로 바뀐 순간부터 HIGH로 바뀌는 순간까지의 경과시간을 마이크로초 단위로 Thro변수에 저장. 
    // 만약, 50ms시간동안 펄스의 변화가 없다면, 0값이 Thro변수에 저장된다.
    Gear = pulseIn(A2, HIGH, 50000);  //SWA,CH5
    // 아날로그2번 핀의 pwm입력신호가 LOW로 바뀐 순간부터 HIGH로 바뀌는 순간까지의 경과시간을 마이크로초 단위로 Gear변수에 저장. 
    // 만약, 50ms시간동안 펄스의 변화가 없다면, 0값이 Gear변수에 저장된다.
    Aux = pulseIn(A3, HIGH, 50000);   //VRA,CH6 +1 전진, -1 후진 
    // 아날로그1번 핀의 pwm입력신호가 LOW로 바뀐 순간부터 HIGH로 바뀌는 순간까지의 경과시간을 마이크로초 단위로 Aux변수에 저장. 
    // 만약, 50ms시간동안 펄스의 변화가 없다면, 0값이 Aux변수에 저장된다.


    T = Thro/50; Thro = T*50; A = Aux/50; Aux = A*50; G = Gear/50; Gear = G*50; AL = ALIE/50; ALIE = AL*50; // 조종기 신호 안정화

    if(ALIE>1700){ ALIE=1700; } else if(ALIE<1000){ ALIE = 1000; } // 조종기 ALIE(조향) 신호 최대 최소값 제한
    if(Thro>1600){ Thro=1600; }  else if(Thro<1000){ ESTOP = 1;} else{ESTOP=0;} // 조종기 THRO(구동) 신호 최대값 제한, Throttle Cut할때 ESTOP신호 주도록 설정 
    //1850
    Speed = map(Thro, 1050, 1850, -255, 255); // 조종기 THRO 신호를 Speed값으로 변환 
    if(Speed>255){ Speed = 255; } else if(Speed<10 or ESTOP == 1 ){ Speed = 0; } // Speed값 최대 최소값 제한 및 ESTOP상황에서 멈추도록 설정
    Steer = map(ALIE, 1200, 1700,1023, 0); // 조종기 ALIE 신호를 Steer값으로 변환 //초속 3.6
    if(Steer>St_M+400){ Steer = St_M+400; } else if(Steer<St_M-400){ Steer = St_M-400; } // Steer값 최대 최소값 제한
    else if(Steer>St_M-20 and Steer<St_M+20){ Steer = St_M;} // 조향 유지를 위한 DeadZone

    if(Aux>1700){ Mode = 0;} else if(Aux<1700 and Aux>1300){ Mode = 1; Speed = 0; } else if(Aux<1300){ Mode = 2; }
    // 조종기 Aux신호를 주행 상태결정하는 Mode변수로 치환, Mode=0:직진, Mode=1:중립, Mode=2:후진 

    if(Gear>500 and Aux > 500){ // 조종기가 On일때 
     if(Gear<1200){ State = 1; } else{ State = 0; } 
    // 조종기 Gear신호를 통해 자율주행모드, 수동주행모드 설정. State = 1:Auto mode, State = 0: Manual mode
     }
    else{ Speed = 0; Steer = 500; }  // 조종기가 Off일때 속도 0 조향 0
}
728x90

'자율주행자동차 > [2023] 1-fifth AA EV' 카테고리의 다른 글

[D-Week] 현재로부터 해야 할 일  (0) 2023.04.22
[D-2weeks] 수동 조작 제어 및 앞으로 할 일  (0) 2023.04.17
깃에 옮기기  (0) 2023.04.16
'자율주행자동차/[2023] 1-fifth AA EV' 카테고리의 다른 글
  • [D-Week] 현재로부터 해야 할 일
  • [D-2weeks] 수동 조작 제어 및 앞으로 할 일
  • 깃에 옮기기
뚱이, not a starfish
뚱이, not a starfish
M.S. Student,. Mainly interested in computer vision and autonomous cars
  • 뚱이, not a starfish
    Wilbur-Babo
    뚱이, not a starfish
  • 전체
    오늘
    어제
    • 분류 전체보기 (195)
      • Computer Graphics (0)
      • Algorithm (22)
        • BOJ (21)
        • 삼성 SW 역량 테스트 (0)
      • 통신 및 네트워크 (12)
      • Embedded Projects (2)
      • AI-Paper (10)
        • 3D-GS (1)
        • Mono-Depth (7)
        • Base (2)
      • AI-Study (16)
        • Computer Vision (1)
        • Tiny Object Detection (3)
      • Image Processing (3)
      • 자율주행자동차 (20)
        • [2023] 1-fifth AA EV (4)
        • [2022] 1-tenth AA EV (2)
        • ROS 1,2 (4)
        • 이론 (7)
        • 실습 (3)
      • 전기전자공학(전공) (12)
        • 반도체 (2)
        • 마이크로프로세서 (6)
      • EVS37 Ambassador (5)
      • .0 (9)
      • sw (16)
        • 정보보안 (1)
        • Android_develop (3)
      • 차량 제어 플랫폼 (5)
      • 영어 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    오블완챌린지
    EVS37
    현대자동차 연구개발
    현차떨
    자율주행시험
    software defined vehicle
    자율주행자동차
    현대자동차 서류합격후기
    tar압축풀기
    evs37 sdv
    오픽후기
    우분투터미널
    rc카
    현차 3월 자율주행
    tar 파일
    정렬
    현대자동차 자율주행 서류 합격 후기
    자율주행
    현대자동차최종불합
    헤네스유아용자동차
    자율주행작품
    현대자동차 자율주행
    헤네스
    심포지움
    현차 자율주행
    evs37sdv
    현대차3월신입후기
    현대자동차최종면접결과
    자율주행경진대회
    현차 3월 신입 서류
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
뚱이, not a starfish
....
상단으로

티스토리툴바